bzoj1901 线段树套主席树
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<map> #define maxn 120000 using namespace std; int ls[maxn*20],rs[maxn*20],sum[maxn*20]; int root[maxn],tot; void update(int fa,int p,int l,int r,int &rt,int v){ rt=++tot; ls[rt]=ls[fa],rs[rt]=rs[fa],sum[rt]=sum[fa]+v; if(l==r)return; int mid=l+r>>1; if(p<=mid)update(ls[fa],p,l,mid,ls[rt],v); else update(rs[fa],p,mid+1,r,rs[rt],v); } int cc,n,m; int num[maxn]; char op[maxn]; #define NN 10010 int san[NN*2],P[NN],Q[NN],K[NN]; int L[30],R[30]; int N,M; int query(int l,int r,int k){ if(l==r)return l; int mid=l+r>>1; int suma=0,sumb=0; for(int i=1;i<=N;i++)suma+=sum[ls[L[i]]]; for(int i=1;i<=M;i++)sumb+=sum[ls[R[i]]]; int del=sumb-suma; if(k<=del){ for(int i=1;i<=N;i++)L[i]=ls[L[i]]; for(int i=1;i<=M;i++)R[i]=ls[R[i]]; return query(l,mid,k); }else{ for(int i=1;i<=N;i++)L[i]=rs[L[i]]; for(int i=1;i<=M;i++)R[i]=rs[R[i]]; return query(mid+1,r,k-del); } } int ask(int l,int r,int k){ N=0,M=0; for(;l>0;l-=l&-l)L[++N]=root[l]; for(;r>0;r-=r&-r)R[++M]=root[r]; return query(1,cc,k); } void change(int x,int val,int v){ for(;x<=n;x+=x&-x){ update(root[x],val,1,cc,root[x],v); } } int sn; int rank[NN*2]; int rr(int x){ int l=0,r=cc; while(l+1!=r){ int mid=l+r>>1; if(rank[mid]>=x)r=mid; else l=mid; } return r; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&num[i]); san[++sn]=num[i]; } for(int i=1;i<=m;i++){ scanf(" %c",&op[i]); scanf("%d%d",&P[i],&Q[i]); if(op[i]=='Q')scanf("%d",&K[i]); else san[++sn]=Q[i]; } sort(san+1,san+sn+1); for(int i=1;i<=sn;i++){ if(i==1||san[i]!=san[i-1])cc++; rank[cc]=san[i]; } for(int i=1;i<=n;i++)num[i]=rr(num[i]); for(int i=1;i<=n;i++)change(i,num[i],1); for(int i=1;i<=m;i++){ if(op[i]=='Q'){ int ans=ask(P[i]-1,Q[i],K[i]); printf("%d\n",rank[ans]); }else{ change(P[i],num[P[i]],-1); num[P[i]]=rr(Q[i]); change(P[i],num[P[i]],1); } } }