ZOJ2112 BZOJ1901 Dynamic Rankings 树套树 带修改的区间第k小
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112
树套树,线段树套splay或者主席树套树状数组,我抄了一下hzwer的代码在zoj上过不了因为zoj的数据比较大不能像hzwer那种写法一样写成nlognlogn的空间。
没有bzoj权限号也不想再写一遍,随便放个代码在这里好惹。
https://www.cnblogs.com/kuangbin/p/3308118.html <-----这个写法的空间复杂度可以过(就是把树状数组放到外面直接搞),所以ctm我为什么抄hzwer的代码。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 const int maxn=50010; 7 using namespace std; 8 char s[3]={}; int n,m; 9 int val[maxn]={},a[maxn]={},b[maxn]={},k[maxn]={}; 10 int num[maxn*2]={},tot=0,flag[maxn]={}; 11 int sum[maxn*50],lc[maxn*50],rc[maxn*50]; 12 int rt[maxn]={},siz=0; 13 int ll[maxn]={},rr[maxn]={},xx,yy; 14 void build(int l,int r,int las,int &rot,int z,int v){ 15 rot=++siz; sum[rot]=sum[las]+v; lc[rot]=lc[las]; rc[rot]=rc[las]; 16 if(l==r)return; 17 int mid=(l+r)/2; 18 if(z<=mid)build(l,mid,lc[las],lc[rot],z,v); 19 else build(mid+1,r,rc[las],rc[rot],z,v); 20 } 21 int query(int l,int r,int z){ 22 if(l==r)return l; 23 int suml=0,sumr=0; 24 for(int i=1;i<=xx;i++)suml+=sum[lc[ll[i]]]; 25 for(int i=1;i<=yy;i++)sumr+=sum[lc[rr[i]]]; 26 int mid=(l+r)/2; 27 if(sumr-suml>=z){ 28 for(int i=1;i<=xx;i++)ll[i]=lc[ll[i]]; 29 for(int i=1;i<=yy;i++)rr[i]=lc[rr[i]]; 30 return query(l,mid,z); 31 } 32 else{ 33 for(int i=1;i<=xx;i++)ll[i]=rc[ll[i]]; 34 for(int i=1;i<=yy;i++)rr[i]=rc[rr[i]]; 35 return query(mid+1,r,z-(sumr-suml)); 36 } 37 } 38 int main(){ 39 int T;scanf("%d",&T); 40 while(T-->0){ 41 scanf("%d%d",&n,&m); 42 tot=0;siz=0; 43 memset(rt,0,sizeof(rt));memset(sum,0,sizeof(sum)); 44 memset(rc,0,sizeof(rc));memset(lc,0,sizeof(lc)); 45 memset(flag,0,sizeof(flag)); 46 for(int i=1;i<=n;i++){scanf("%d",&val[i]);num[++tot]=val[i];} 47 for(int i=1;i<=m;i++){ 48 scanf("%s",s);scanf("%d%d",&a[i],&b[i]); 49 if(s[0]=='C')num[++tot]=b[i]; 50 else{scanf("%d",&k[i]);flag[i]=1;} 51 } 52 sort(num+1,num+tot+1); 53 tot=unique(num+1,num+tot+1)-num-1; 54 for(int i=1;i<=n;i++){ 55 val[i]=lower_bound(num+1,num+1+tot,val[i])-num; 56 for(int j=i;j<=n;j+=(j&-j)) 57 build(1,tot,rt[j],rt[j],val[i],1); 58 } 59 for(int i=1;i<=m;i++){ 60 if(flag[i]){ 61 xx=0;yy=0;a[i]--;//cout<<a[i]<<b[i]<<endl; 62 for(int j=a[i];j;j-=(j&-j))ll[++xx]=rt[j]; 63 for(int j=b[i];j;j-=(j&-j))rr[++yy]=rt[j]; 64 printf("%d\n",num[query(1,tot,k[i])]); 65 } 66 else{ 67 for(int j=a[i];j<=n;j+=(j&-j))build(1,tot,rt[j],rt[j],val[a[i]],-1); 68 val[a[i]]=lower_bound(num+1,num+1+tot,b[i])-num; 69 for(int j=a[i];j<=n;j+=(j&-j))build(1,tot,rt[j],rt[j],val[a[i]],1); 70 } 71 } 72 } 73 return 0; 74 }
所以直接找可持久化线段树的题好了,找主席树出来的都是什么jb。