​点击打开链接​

第一次写主席树 存模板

推荐一个学长的博客 有图就是好理解

#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;

struct node
{
int l;
int r;
int val;
};

node tree[2000010];
int root[100010],ary[100010],tmp[100010];
int n,len,q,num;

int build(int l,int r)
{
int cur,m;
cur=num++;
tree[cur].l=0,tree[cur].r=0,tree[cur].val=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].l=build(l,m);
tree[cur].r=build(m+1,r);
return cur;
}

int update(int rot,int tar,int l,int r)
{
int cur,m;
cur=num++;
tree[cur]=tree[rot];
tree[cur].val++;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].l=update(tree[rot].l,tar,l,m);
else tree[cur].r=update(tree[rot].r,tar,m+1,r);
return cur;
}

int query(int lrot,int rrot,int k,int l,int r)
{
int m;
if(l==r) return l;
m=(l+r)/2;
if(tree[tree[rrot].l].val-tree[tree[lrot].l].val>=k) return query(tree[lrot].l,tree[rrot].l,k,l,m);
else return query(tree[lrot].r,tree[rrot].r,k-(tree[tree[rrot].l].val-tree[tree[lrot].l].val),m+1,r);
}

int main()
{
int i,l,r,k,pos;
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++)
{
scanf("%d",&ary[i]);
tmp[i]=ary[i];
}
sort(tmp+1,tmp+n+1);
len=unique(tmp+1,tmp+n+1)-tmp-1;
num=0;
root[0]=build(1,len);
for(i=1;i<=n;i++)
{
pos=lower_bound(tmp+1,tmp+len+1,ary[i])-tmp;
root[i]=update(root[i-1],pos,1,len);
}
while(q--)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",tmp[query(root[l-1],root[r],k,1,len)]);
}
return 0;
}

划分树模板 感觉划分树比较鸡肋 主要解决一些卡常数的SB题

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int tree[20][100010];
int lef[20][100010];
int num[100010];
int n,q;

void build(int l,int r,int dep)
{
int i,m,same,lpos,rpos;
if(l==r) return;
m=(l+r)/2,same=m-l+1;
for(i=l;i<=r;i++)
{
if(tree[dep][i]<num[m]) same--;
}
lpos=l,rpos=m+1;
for(i=l;i<=r;i++)
{
if(tree[dep][i]<num[m])
{
tree[dep+1][lpos++]=tree[dep][i];
}
else if(tree[dep][i]==num[m]&&same>0)
{
tree[dep+1][lpos++]=tree[dep][i];
same--;
}
else
{
tree[dep+1][rpos++]=tree[dep][i];
}
lef[dep][i]=lef[dep][l-1]+lpos-l;
}
build(l,m,dep+1);
build(m+1,r,dep+1);
}

int query(int pl,int pr,int k,int l,int r,int dep)
{
int cnt,m,newl,newr;
if(pl==pr) return tree[dep][pl];
cnt=lef[dep][pr]-lef[dep][pl-1],m=(l+r)/2;
if(cnt>=k)
{
newl=l+lef[dep][pl-1]-lef[dep][l-1];
newr=newl+cnt-1;
return query(newl,newr,k,l,m,dep+1);
}
else
{
newr=pr+lef[dep][r]-lef[dep][pr];
newl=newr-(pr-pl-cnt);
return query(newl,newr,k-cnt,m+1,r,dep+1);
}
}

int main()
{
int i,l,r,k;
while(scanf("%d%d",&n,&q)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
tree[0][i]=num[i];
}
sort(num+1,num+n+1);
build(1,n,0);
while(q--)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",query(l,r,k,1,n,0));
}
}
return 0;
}