洛谷 2042 BZOJ 1500 NOI 2005 维护数列
【题意概述】
维护一个数列,要求支持以下6种操作:
【题解】
大Boss。。。可以用Treap解决
需要用到垃圾回收、线性建树。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ls (a[u].l) 5 #define rs (a[u].r) 6 using namespace std; 7 const int maxn=500010; 8 int n,m,k,x,y,z,top,root,recs[maxn],bs[maxn];//recs-->recycle_stack, bs-->build_stack 9 char c,c2; 10 struct treap{int l,r,size,rnd,v,sum,max,lsum,rsum,num; bool same,rev;}a[maxn]; 11 inline int read(){ 12 int k=0,f=1; char c=getchar(); 13 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 14 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 15 return k*f; 16 } 17 inline int max(int x,int y){return x>y?x:y;} 18 inline int newnode(int v){a[recs[top--]]=(treap){0,0,1,rand(),v,v,v,v,v,0,0,0}; return recs[top+1];}//新建节点 19 void recycle(int u){if(u) recs[++top]=u,recycle(ls),recycle(rs);}//垃圾回收 20 inline void reverse(int u){//区间翻转 21 swap(ls,rs); swap(a[u].lsum,a[u].rsum); 22 a[ls].rev^=1; a[rs].rev^=1; 23 } 24 inline void set_same(int u,int v){//区间设为同个数 25 a[u].same=1; a[u].v=a[u].num=v; a[u].sum=v*a[u].size; 26 a[u].max=a[u].lsum=a[u].rsum=(v>=0?a[u].sum:v); 27 } 28 void down(int u){//下传标记 29 if(a[u].rev){ 30 if(ls) reverse(ls); 31 if(rs) reverse(rs); 32 a[u].rev^=1; 33 } 34 if(a[u].same){ 35 if(ls) set_same(ls,a[u].num); 36 if(rs) set_same(rs,a[u].num); 37 a[u].same=a[u].num=0; 38 } 39 } 40 void up(int u){//上传标记 41 a[u].size=a[ls].size+a[rs].size+1; 42 a[u].sum=a[ls].sum+a[rs].sum+a[u].v; 43 a[u].max=max(max(a[ls].max,a[rs].max),max(a[ls].rsum,0)+a[u].v+max(a[rs].lsum,0)); 44 a[u].lsum=max(a[ls].lsum,a[ls].sum+a[u].v+max(a[rs].lsum,0)); 45 a[u].rsum=max(a[rs].rsum,a[rs].sum+a[u].v+max(a[ls].rsum,0)); 46 } 47 void split(int u,int k,int &x,int &y){//分裂 48 down(u); 49 if(!k){x=0; y=u; return;} 50 if(a[u].size==k){x=u; y=0; return;} 51 if(a[ls].size>=k) split(ls,k,x,ls),y=u; 52 else split(rs,k-a[ls].size-1,rs,y),x=u; 53 up(u); 54 } 55 int merge(int x,int y){//合并 56 if(!x||!y) return x+y; 57 if(a[x].rnd<a[y].rnd){down(x); a[x].r=merge(a[x].r,y); up(x); return x;} 58 else{down(y); a[y].l=merge(x,a[y].l); up(y); return y;} 59 } 60 void build(int &root,int n){//线性建树 61 int bstop=0; bs[++bstop]=newnode(read()); 62 for(int i=1;i<n;i++){ 63 int now=newnode(read()); 64 while(top&&a[now].rnd<a[bs[bstop]].rnd) up(bs[bstop]),a[now].l=bs[bstop--]; 65 if(bstop) a[bs[bstop]].r=now; 66 bs[++bstop]=now; 67 } 68 while(bstop) up(bs[bstop--]); 69 root=bs[1]; 70 } 71 void out(int u){ 72 if(ls) out(ls); 73 printf("%d ",a[u].v); 74 if(rs) out(rs); 75 } 76 void Insert(){//插入 77 int x,y,insroot=0; 78 split(root,read(),x,y); 79 build(insroot,read()); 80 root=merge(x,merge(insroot,y)); 81 //out(root); 82 } 83 void Delete(){recycle(y); y=0;}//删除 84 void Prepare(){ 85 srand(0); 86 for(int i=maxn;i;i--) recs[++top]=i; 87 a[0].max=a[0].lsum=a[0].rsum=-2e9; 88 } 89 int main(){ 90 Prepare(); 91 n=read(); m=read(); build(root,n); //out(root); 92 //for(int i=1;i<=n;i++) root=merge(root,newnode(read())); 93 while(m--){ 94 c=getchar(); while(c!='I'&&c!='D'&&c!='K'&&c!='R'&&c!='G'&&c!='X') c=getchar(); 95 c2=getchar(); while(c2!='-'&&c2!=' ') c2=getchar(); 96 if(c=='X'){//max_sum 97 printf("%d\n",a[root].same?(a[root].num?a[root].num*a[root].size:a[root].num):a[root].max); 98 continue; 99 } 100 if(c=='I'){Insert(); continue;}//insert 101 split(root,read()-1,x,y); 102 split(y,read(),y,z); 103 if(c=='D') Delete();//delete 104 if(c=='K') set_same(y,read());//set_same 105 if(c=='R') a[y].rev^=1,reverse(y);//reverse 106 if(c=='G') printf("%d\n",a[y].same?a[y].num*a[y].size:a[y].sum);//get_sum 107 root=merge(merge(x,y),z); 108 } 109 return 0; 110 }