[NOI2005]维护数列

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

HINT

题解:

听说做了这道题splay就差不多过关了。(然而我调了一天)

关于问题中的几个操作:

1.插入

将输入的数列用建二叉树的方式建成一棵splay,然后将目标位置的那个节点旋转到根,再将后面那个节点旋转到根的下方(就是split操作),然后就直接将新的splay接到根节点的右子节点的左子节点上。

2.删除

也是像之前一样,用split操作将删除的区间确定在根节点的右子节点的左子节点处,然后将删除的区间加入内存池就好了。

 

3.修改

先split一下,然后在根节点的右子节点的左子节点打上修改标记。

 

4.旋转

先split一下,然后在根节点的右子节点的左子节点打上旋转标记。

 

5.求和

先split一下,直接输出根节点右子节点的左子节点的sum。

 

6.求和最大的子列

就像线段树维护一样,对于每一个节点,我们令它所控制的区间是以它为根节点子树,然后维护三个参数ls,rs,ms。分别表示这个区间左边最大的子列,右边最大的子列,中间最大的子列。然后每次push_up的时候跟新一下就好。

当然这道题目很折磨人,有很多细节:

1.splay维护区间的时候要在一头一尾加上一个极值,因为如果不加,find可能会找不到

2.输出和最大的子列的时候也是需要split的,因为两端的极值会对根节点的三个参数造成影响。

3.push_up和push_down中维护ls,rs,ms的部分有些地方要和0取max,详见代码。

4.在find中push_down(这个是套路)

  1 //Never forget why you start
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<algorithm>
  8 #include<queue>
  9 #define inf (0x3f3f3f3f)
 10 #define ll(x) bst[x].child[0]
 11 #define rr(x) bst[x].child[1]
 12 #define son(x,t) bst[x].child[t]
 13 using namespace std;
 14 int n,m,cnt;
 15 int pos[1000005],root,a[1000005];
 16 struct Bst{
 17   int child[2],fa,size,sum,x,lazy,round,ls,rs,ms,islazy;
 18 }bst[1000005];
 19 queue<int>mem;
 20 void push_up(int rt){
 21   int l=ll(rt),r=rr(rt);
 22   bst[rt].sum=bst[l].sum+bst[r].sum+bst[rt].x;
 23   bst[rt].size=bst[l].size+bst[r].size+1;
 24   bst[rt].ls=bst[rt].rs=bst[rt].ms=-inf;
 25   bst[rt].ms=max(max(0,bst[l].rs)+bst[rt].x+max(0,bst[r].ls),max(bst[l].ms,bst[r].ms));
 26   bst[rt].rs=max(bst[r].rs,bst[r].sum+bst[rt].x+max(0,bst[l].rs));
 27   bst[rt].ls=max(bst[l].ls,bst[l].sum+bst[rt].x+max(0,bst[r].ls));
 28 }
 29 void rotate(int r,int t){
 30   int fa=bst[r].fa;
 31   son(fa,!t)=son(r,t);bst[son(r,t)].fa=fa;
 32   son(bst[fa].fa,son(bst[fa].fa,1)==fa)=r;bst[r].fa=bst[fa].fa;
 33   son(r,t)=fa;bst[fa].fa=r;
 34   push_up(fa);
 35   push_up(r);
 36 }
 37 void splay(int r,int goal){
 38   int fa=bst[r].fa;
 39   while(fa!=goal){
 40     if(bst[fa].fa==goal)rotate(r,son(fa,0)==r);
 41     else{
 42       int t=son(bst[fa].fa,0)==fa;
 43       if(son(fa,t)==r)rotate(r,!t),rotate(r,t);
 44       else rotate(fa,t),rotate(r,t);
 45     }
 46     fa=bst[r].fa;
 47   }
 48   if(goal==0)root=r;
 49 }
 50 void push_down(int root){
 51   int l=son(root,0),r=son(root,1);
 52   if(bst[root].round){
 53     bst[l].round^=1;bst[r].round^=1;
 54     swap(son(root,0),son(root,1));
 55     swap(bst[l].ls,bst[l].rs);
 56     swap(bst[r].ls,bst[r].rs);
 57     bst[root].round=0;
 58   }
 59   if(bst[root].islazy){
 60     if(l)bst[l].islazy=1,bst[l].lazy=bst[root].x,bst[l].x=bst[root].x,bst[l].sum=bst[l].size*bst[root].x;
 61     if(r)bst[r].islazy=1,bst[r].lazy=bst[root].x,bst[r].x=bst[root].x,bst[r].sum=bst[r].size*bst[root].x;
 62     if(bst[root].lazy>=0){
 63       bst[l].ls=bst[l].rs=bst[l].ms=bst[l].sum;
 64       bst[r].ls=bst[r].rs=bst[r].ms=bst[r].sum;
 65     }
 66     else{
 67       bst[l].ls=bst[l].rs=bst[l].ms=bst[root].x;
 68       bst[r].ls=bst[r].rs=bst[r].ms=bst[root].x;
 69     }
 70     bst[root].lazy=0;
 71     bst[root].islazy=0;
 72   }
 73 }
 74 int find(int r,int k){
 75   push_down(r);
 76   int y=bst[son(r,0)].size;
 77   if(y+1==k)return r;
 78   else if(y>=k)return find(ll(r),k);
 79   else return find(rr(r),k-y-1);
 80 }
 81 int newnode(){
 82   int pos;
 83   if(!mem.empty())pos=mem.front(),mem.pop();
 84   else pos=++cnt;
 85   bst[pos].child[0]=bst[pos].child[1]=bst[pos].fa=0;
 86   bst[pos].islazy=bst[pos].lazy=bst[pos].round=0;
 87   bst[pos].rs=bst[pos].ls=bst[pos].ms=-inf;
 88   bst[pos].sum=bst[pos].x=0;
 89   bst[pos].size=1;
 90   return pos;
 91 }
 92 void build(int l,int r,int fa,int f){
 93   int mid=(l+r)>>1,now=pos[mid]=newnode();
 94   if(l==r){
 95     bst[now].sum=bst[now].x=a[l];
 96     bst[now].ls=bst[now].rs=bst[now].ms=a[l];
 97   }
 98   if(l<mid)build(l,mid-1,now,mid);
 99   if(mid<r)build(mid+1,r,now,mid);
100   bst[now].x=a[mid];bst[now].fa=fa;
101   push_up(now);
102   son(fa,mid>=f)=now;
103 }
104 void insert(int place,int tot){
105   int i;
106   for(i=1;i<=tot;i++)
107     scanf("%d",&a[i]);
108   build(1,tot,0,0);
109   int rt=pos[(tot+1)>>1],x=find(root,place),y=find(root,place+1);
110   splay(x,0);splay(y,x);
111   son(y,0)=rt;bst[rt].fa=y;
112   push_up(y);
113   push_up(x);
114 }
115 void clean(int r){
116   if(r){
117     mem.push(r);
118     clean(son(r,0));
119     clean(son(r,1));
120   }
121 }
122 void delet(int place,int tot){
123   int x=find(root,place-1),y=find(root,place+tot);
124   splay(x,0);splay(y,x);
125   clean(son(y,0));
126   son(y,0)=0;
127   push_up(y);push_up(x);
128 }
129 void make_same(int place,int tot,int c){
130   int x=find(root,place-1),y=find(root,place+tot);
131   splay(x,0);splay(y,x);
132   int z=son(y,0);
133   bst[z].sum=c*bst[z].size;
134   bst[z].lazy=c;
135   bst[z].islazy=1;
136   bst[z].x=c;
137   if(c>=0){
138     bst[z].ls=bst[z].rs=bst[z].ms=c*bst[z].size;
139   }
140   else{
141     bst[z].ls=bst[z].rs=bst[z].ms=c;
142   }
143   push_up(y);push_up(x);
144 }
145 void rever(int place,int tot){
146   int x=find(root,place-1),y=find(root,place+tot);
147   splay(x,0);splay(y,x);
148   int z=son(y,0);
149   bst[z].round^=1;
150   swap(bst[z].ls,bst[z].rs);
151   push_up(y);push_up(x);
152 }
153 int get_sum(int place,int tot){
154   int x=find(root,place-1),y=find(root,place+tot);
155   splay(x,0);splay(y,x);
156   return bst[son(y,0)].sum;
157 }
158 int max_sum(){
159   int x=find(root,1),y=find(root,bst[root].size);
160   splay(x,0);splay(y,x);
161   return bst[son(y,0)].ms;
162 }
163 int main(){
164   int i,j;
165   scanf("%d%d",&n,&m);
166   a[1]=-inf;a[n+2]=-inf;
167   for(i=1;i<=n;i++)
168     scanf("%d",&a[i+1]);
169   n+=2;
170   build(1,n,0,0);
171   root=pos[(1+n)>>1];
172   for(i=1;i<=m;i++){
173     char s[10];int place,tot,c;
174     scanf("%s",s);
175     if(s[0]=='I')scanf("%d%d",&place,&tot),insert(place+1,tot);
176     if(s[0]=='D')scanf("%d%d",&place,&tot),delet(place+1,tot);
177     if(s[0]=='M'&&s[2]=='K')scanf("%d%d%d",&place,&tot,&c),make_same(place+1,tot,c);
178     if(s[0]=='R')scanf("%d%d",&place,&tot),rever(place+1,tot);
179     if(s[0]=='G')scanf("%d%d",&place,&tot),printf("%d\n",get_sum(place+1,tot));
180     if(s[0]=='M'&&s[2]=='X')printf("%d\n",max_sum());
181   }
182   return 0;
183 }

 

posted @ 2018-01-10 07:59  kakakakakaka  阅读(185)  评论(0编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效