题解:
可修改的主席树
一开始,我就按照最暴力的方法,空间nlognlogn
然后zju上面过不了,bzoj没有权限号
然后,参考了往上的论文,发现可以把初始的主席树先建好
然后,每次只需要维护修改的就可以了
而且修改的内容只有2个数字
可以快那么一些
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define ls(x) t[x].lc #define rs(x) t[x].rc typedef long long ll; const int N=50005; int read() { char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int q1[N],t1,q2[N],t2,sz=0,root[N],rt[N],n,Q,m,a[N],mp[N*2],i,j,k; char s[2]; struct question { char s[3]; int i,j,k,x,d; }q[N]; struct node { int lc,rc,w; }t[N*50]; int Bin(int v) { int l=1,r=m; while (l<=r) { int mid=(l+r)>>1; if(mp[mid]==v) return mid; if(mp[mid]>v) r=mid-1; else l=mid+1; } return -1; } void ins(int &x,int l,int r,int num,int v) { t[++sz]=t[x];x=sz; t[x].w+=v; if(l==r) return; int mid=(l+r)>>1; if (num<=mid) ins(t[x].lc,l,mid,num,v); else ins(t[x].rc,mid+1,r,num,v); } void add(int p,int v) { int xx=Bin(a[p]); for (int i=p;i<=n;i+=i&-i) ins(root[i],1,m,xx,v); } int cal() { int sum1=0,sum2=0; for (int i=1;i<=t1;i++) sum1+=t[ls(q1[i])].w; for (int i=1;i<=t2;i++) sum2+=t[ls(q2[i])].w; return sum2-sum1; } int query(int ql,int qr,int k) { int l=1,r=m;t1=t2=0; for (int i=ql-1;i;i-=i&-i) q1[++t1]=root[i]; for (int i=qr;i;i-=i&-i) q2[++t2]=root[i]; ql--; ql=rt[ql];qr=rt[qr]; while (l<r) { int lsize=cal()+t[ls(qr)].w-t[ls(ql)].w,mid=(l+r)>>1; if (k<=lsize) { for (int i=1;i<=t1;i++) q1[i]=t[q1[i]].lc; for (int i=1;i<=t2;i++) q2[i]=t[q2[i]].lc; ql=ls(ql);qr=ls(qr); r=mid; } else { for (int i=1;i<=t1;i++) q1[i]=t[q1[i]].rc; for (int i=1;i<=t2;i++) q2[i]=t[q2[i]].rc; ql=rs(ql);qr=rs(qr); l=mid+1;k-=lsize; } } return l; } int main() { int T=read(); while (T--) { m=sz=0; memset(q,0,sizeof q); memset(t,0,sizeof t); memset(rt,0,sizeof rt); memset(root,0,sizeof root); n=read();Q=read(); for (int i=1;i<=n;i++)a[i]=mp[++m]=read(); for (int i=1;i<=Q;i++) { scanf("%s",q[i].s); if (q[i].s[0]=='Q') q[i].i=read(),q[i].j=read(),q[i].k=read(); else q[i].x=read(),q[i].d=mp[++m]=read(); } sort(mp+1,mp+1+m); int p=1; for (int i=2;i<=m;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i]; m=p; for (int i=1;i<=n;i++) rt[i]=rt[i-1],ins(rt[i],1,m,Bin(a[i]),1); for (int i=1;i<=Q;i++) { if(q[i].s[0]=='Q') printf("%d ",mp[query(q[i].i,q[i].j,q[i].k)]); else { add(q[i].x,-1); a[q[i].x]=q[i].d; add(q[i].x,1); } } } return 0; }