树状维护区间,内部主席树(动态开点)维护值域;
树状数组的结点i代表第i个版本的权值线段树并且其是建立在原区间 [ i - lowbit(i) + 1 , i ] ;
通过树状数组对结点(每个节点都是一个线段树)求和,就能得到一个完整版本的主席树;
由于树状数组的特殊性,这里不需要保存历史版本,直接通过树状向上更新即可;
我的代码是递归的写法,有点耗内存
^(* ̄(oo) ̄)^ ZOJ上死活过不了,不是段错误就是超内存,这32M内存做主席树的题真的是一把辛酸泪,但是洛谷过了,先挂洛谷的递归AC代码;
用循环搞搞ZOJ压压内存,等过了,再贴份代码吧。
#include<bits/stdc++.h> #pragma GCC optimize(2) using namespace std; typedef long long LL; typedef pair<int,int> pii; typedef pair<double,double> pdd; const int N=6e4+5; const int M=1e4+5; const int inf=0x3f3f3f3f; const int mod=1e9+7; const double eps=1e-9; const long double pi=acos(-1.0L); #define ls (i<<1) #define rs (i<<1|1) #define fi first #define se second #define pb push_back #define mk make_pair #define mem(a,b) memset(a,b,sizeof(a)) LL read() { LL x=0,t=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') t=-1; while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } return x*t; } struct node{ int l,r,v; }c[40*N]; int root[N],t[N+M],a[N],L[M],R[M],K[M],cmd[M],len,tot,n,m,cnt; int qx[N],qy[N],tx,ty; void update(int l,int r,int &now,int pos,int d) { if(now==0) now=++cnt; c[now].v+=d; if(l==r) return ; int mid=l+r>>1; if(pos<=mid) update(l,mid,c[now].l,pos,d); else update(mid+1,r,c[now].r,pos,d); } inline int lowbit(int x) { return x&(-x); } void add(int x,int y) { for(int i=x;i<=n;i+=lowbit(i)) update(1,len,root[i],a[x],y); } int query(int l,int r,int k) { if(l==r) return l; int mid=l+r>>1; int sum=0; for(int i=1;i<=ty;i++) sum+=c[c[qy[i]].l].v; for(int i=1;i<=tx;i++) sum-=c[c[qx[i]].l].v; if(k<=sum) { for(int i=1;i<=ty;i++) qy[i]=c[qy[i]].l; for(int i=1;i<=tx;i++) qx[i]=c[qx[i]].l; return query(l,mid,k); } else { for(int i=1;i<=ty;i++) qy[i]=c[qy[i]].r; for(int i=1;i<=tx;i++) qx[i]=c[qx[i]].r; return query(mid+1,r,k-sum); } } int main() { int T=1; while(T--) { for(int i=1;i<=cnt;i++) root[i]=c[i].l=c[i].r=c[i].v=0; cnt=tx=ty=0; tot=n=read(),m=read(); for(int i=1;i<=n;i++) t[i]=a[i]=read(); for(int i=1;i<=m;i++) { char ch[2]; int x,y,z; scanf("%s",ch); cmd[i]=ch[0]; if(ch[0]=='Q') L[i]=read(),R[i]=read(),K[i]=read(); else L[i]=read(),t[++tot]=R[i]=read(); } sort(t+1,t+tot+1); len=unique(t+1,t+tot+1)-t-1; //for(int i=1;i<=len;i++) printf("%d%c",t[i],i==len?'\n':' '); for(int i=1;i<=n;i++) a[i]=lower_bound(t+1,t+len+1,a[i])-t; for(int i=1;i<=n;i++) add(i,1); for(int i=1;i<=m;i++) { if(cmd[i]=='Q') { tx=ty=0; for(int j=L[i]-1;j;j-=lowbit(j)) qx[++tx]=root[j]; for(int j=R[i];j;j-=lowbit(j)) qy[++ty]=root[j]; printf("%d\n",t[query(1,len,K[i])]); } else { add(L[i],-1); a[L[i]]=lower_bound(t+1,t+len+1,R[i])-t; add(L[i],1); } } } return 0; }