# BZOJ1901 dynamic ranking-带修主席树

Solution（普通的主席树相信大家都会，如果没学过建议先去学学再来看这篇文章）：

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10010;
int n,qe;
struct Q{
int x,y,k;
}q[10010];
struct tree{
int sum,l,r;
}tr[400*N];
int lsh[2*N];
char s[2];
int root[N];
int size,a[N],maxn;
int x,y,tx[30],ty[30],numx,numy;
void update(int &now,int x,int l,int r,int v,int pos)
{
now=++size;
tr[now]=tr[x];
tr[now].sum+=v;
if (l==r) return;
int mid=l+r>>1;
if (pos<=mid) update(tr[now].l,tr[x].l,l,mid,v,pos);
else update(tr[now].r,tr[x].r,mid+1,r,v,pos);
}
{
int npos=lower_bound(lsh+1,lsh+1+maxn,a[pos])-lsh;
for (int i=pos;i<=n;i+=(i&-i))
update(root[i],root[i],1,maxn,v,npos);
}
int query(int k,int l,int r)
{
if (l==r) return l;
int lsum=0;
for (int i=1;i<=numx;i++)
lsum-=tr[tr[tx[i]].l].sum;
for (int i=1;i<=numy;i++)
lsum+=tr[tr[ty[i]].l].sum;
int mid=l+r>>1;
if (k>lsum)
{
for (int i=1;i<=numx;i++)
tx[i]=tr[tx[i]].r;
for (int i=1;i<=numy;i++)
ty[i]=tr[ty[i]].r;
query(k-lsum,mid+1,r);
}
else
{
for (int i=1;i<=numx;i++)
tx[i]=tr[tx[i]].l;
for (int i=1;i<=numy;i++)
ty[i]=tr[ty[i]].l;
query(k,l,mid);
}
}
{
int f=1,x=0;
char ch;
ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();if(ch=='-')f=-1;}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
int main()
{
for (int i=1;i<=n;i++)
for (int i=1;i<=qe;i++)
{
scanf("%s",s);
else lsh[++maxn]=q[i].y;
}
sort(lsh+1,lsh+1+maxn);
maxn=unique(lsh+1,lsh+1+maxn)-lsh-1;
for (int i=1;i<=qe;i++)
{
if (q[i].k)
{
numx=numy=0;
for (int j=q[i].x-1;j;j-=(j&-j))
tx[++numx]=root[j];
for (int j=q[i].y;j;j-=(j&-j))
ty[++numy]=root[j];
printf("%d\n",lsh[query(q[i].k,1,maxn)]);
}
}