人生第二发树套树。
话说原来树套树跑得比整体二分快啊,真不科学。
整体二分260MS,树套树130MS,快了一倍。
这题嘛就树状数组套主席树。
一开始建一颗空的主席树,以后的树都在这基础上搞。
于是有两套主席树。
第一套是原数组的,依次在前一颗树上建。
第二套是修改出来的主席树,套上树状数组,树状数组修改的时候在之前的树上建。
然后询问的时候要将两套主席树的影响都加上,于是就差不多了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #define lb(x) (x&-x) using namespace std; const int N=60000+10; const int M=2500000+10; int a[N],n,nq,m; int S[N],T[N],lc[M],rc[M],w[M],cnt; int hash[N]; void init(){ sort(hash+1,hash+1+m); m=unique(hash+1,hash+1+m)-hash-1; } int find(int x){ return lower_bound(hash+1,hash+m+1,x)-hash; } int build(int l,int r){ int rt=++cnt; w[rt]=0; if(l!=r){ int mid=l+r>>1; lc[rt]=build(l,mid); rc[rt]=build(mid+1,r); } return rt; } int insert(int rt,int pos,int val){ int nrt=++cnt,tmp=nrt; int l=1,r=m; w[nrt]=w[rt]+val; while(l<r){ int mid=l+r>>1; if(pos<=mid){ lc[nrt]=++cnt;rc[nrt]=rc[rt]; nrt=lc[nrt];rt=lc[rt]; r=mid; }else{ rc[nrt]=++cnt;lc[nrt]=lc[rt]; nrt=rc[nrt];rt=rc[rt]; l=mid+1; } w[nrt]=w[rt]+val; } return tmp; } int use[N]; void add(int x,int p,int d){ for(;x<=n;x+=lb(x))S[x]=insert(S[x],p,d); } int sum(int x){ int ret=0; for(;x>0;x-=lb(x))ret+=w[lc[use[x]]]; return ret; } int query(int a,int b,int k){ int x=T[a-1],y=T[b]; int l=1,r=m; for(int i=a-1;i;i-=lb(i))use[i]=S[i]; for(int i=b;i;i-=lb(i))use[i]=S[i]; while(l<r){ int mid=l+r>>1; int tmp=sum(b)-sum(a-1)+w[lc[y]]-w[lc[x]]; if(tmp>=k){ r=mid; for(int i=a-1;i;i-=lb(i))use[i]=lc[use[i]]; for(int i=b;i;i-=lb(i))use[i]=lc[use[i]]; x=lc[x];y=lc[y]; }else{ l=mid+1; k-=tmp; for(int i=a-1;i;i-=lb(i))use[i]=rc[use[i]]; for(int i=b;i;i-=lb(i))use[i]=rc[use[i]]; x=rc[x];y=rc[y]; } } return l; } struct Query{ int l,r,k,kind; }q[10005]; template<class T>void read(T &x){ static char c; static bool f; for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1; for(x=0;isdigit(c);c=getchar())x=x*10+c-'0'; if(f)x=-x; } int main(){ int kase;read(kase); while(kase--){ read(n);read(nq); cnt=0;m=0; for(int i=1;i<=n;i++){ read(a[i]);hash[++m]=a[i]; } char opt[5]; for(int i=1;i<=nq;i++){ scanf("%s",opt); if(opt[0]=='Q'){ read(q[i].l);read(q[i].r);read(q[i].k); q[i].kind=1; }else{ read(q[i].l);read(q[i].r); q[i].kind=0; hash[++m]=q[i].r; } } init(); T[0]=build(1,m); for(int i=1;i<=n;i++) T[i]=insert(T[i-1],find(a[i]),1); for(int i=1;i<=n;i++)S[i]=T[0]; for(int i=1;i<=nq;i++){ if(q[i].kind)printf("%d\n",hash[query(q[i].l,q[i].r,q[i].k)]); else{ add(q[i].l,find(a[q[i].l]),-1); add(q[i].l,find(q[i].r),1); a[q[i].l]=q[i].r; } } } return 0; }