洛谷 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 }
View Code

 

posted @ 2018-01-07 20:30  Driver_Lao  阅读(143)  评论(0编辑  收藏  举报