BZOJ 1500: [NOI2005]维修数列 (splay tree)

1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 4229  Solved: 1283
[Submit][Status]

Description

Input

输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。

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

 

 

Source

[Submit][Status]


HOME Back


 

 

 

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2013/8/27 3:28:32
  4 File Name     :F:\2013ACM练习\专题学习\splay_tree_2\维修数列.cpp
  5 ************************************************ */
  6 
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <iostream>
 10 #include <algorithm>
 11 #include <vector>
 12 #include <queue>
 13 #include <set>
 14 #include <map>
 15 #include <string>
 16 #include <math.h>
 17 #include <stdlib.h>
 18 #include <time.h>
 19 using namespace std;
 20 
 21 #define Key_value ch[ch[root][1]][0]
 22 const int MAXN = 500010;
 23 const int INF = 0x3f3f3f3f;
 24 int pre[MAXN],ch[MAXN][2],key[MAXN],size[MAXN];
 25 int root,tot1;
 26 int sum[MAXN],rev[MAXN],same[MAXN];
 27 int lx[MAXN],rx[MAXN],mx[MAXN];
 28 int s[MAXN],tot2;//内存池和容量
 29 int a[MAXN];
 30 int n,q;
 31 
 32 //debug部分**********************************
 33 void Treavel(int x)
 34 {
 35     if(x)
 36     {
 37         Treavel(ch[x][0]);
 38         printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d\n",x,ch[x][0],ch[x][1],pre[x],size[x]);
 39         Treavel(ch[x][1]);
 40     }
 41 }
 42 
 43 
 44 void debug()
 45 {
 46     printf("root:%d\n",root);
 47     Treavel(root);
 48 }
 49 //以上是debug部分**************************************
 50 
 51 
 52 void NewNode(int &r,int father,int k)
 53 {
 54     if(tot2) r = s[tot2--];//取的时候是tot2--,存的时候就是++tot2
 55     else r = ++tot1;
 56     pre[r] = father;
 57     ch[r][0] = ch[r][1] = 0;
 58     key[r] = k;
 59     sum[r] = k;
 60     rev[r] = same[r] = 0;
 61     lx[r] = rx[r] = mx[r] = k;
 62     size[r] = 1;
 63 }
 64 void Update_Rev(int r)
 65 {
 66     if(!r)return;
 67     swap(ch[r][0],ch[r][1]);
 68     swap(lx[r],rx[r]);
 69     rev[r] ^= 1;
 70 }
 71 void Update_Same(int r,int v)
 72 {
 73     if(!r)return;
 74     key[r] = v;
 75     sum[r] = v*size[r];
 76     lx[r] = rx[r] = mx[r] = max(v,v*size[r]);
 77     same[r] = 1;
 78 }
 79 void push_up(int r)
 80 {
 81     int lson = ch[r][0], rson = ch[r][1];
 82     size[r] = size[lson] + size[rson] + 1;
 83     sum[r] = sum[lson] + sum[rson] + key[r];
 84     lx[r] = max(lx[lson],sum[lson] + key[r] + max(0,lx[rson]));
 85     rx[r] = max(rx[rson],sum[rson] + key[r] + max(0,rx[lson]));
 86     mx[r] = max(0,rx[lson]) + key[r] + max(0,lx[rson]);
 87     mx[r] = max(mx[r],max(mx[lson],mx[rson]));
 88 }
 89 void push_down(int r)
 90 {
 91     if(same[r])
 92     {
 93         Update_Same(ch[r][0],key[r]);
 94         Update_Same(ch[r][1],key[r]);
 95         same[r] = 0;
 96     }
 97     if(rev[r])
 98     {
 99         Update_Rev(ch[r][0]);
100         Update_Rev(ch[r][1]);
101         rev[r] = 0;
102     }
103 }
104 void Build(int &x,int l,int r,int father)
105 {
106     if(l > r)return;
107     int mid = (l+r)/2;
108     NewNode(x,father,a[mid]);
109     Build(ch[x][0],l,mid-1,x);
110     Build(ch[x][1],mid+1,r,x);
111     push_up(x);
112 }
113 void Init()
114 {
115     root = tot1 = tot2 = 0;
116     ch[root][0] = ch[root][1] = size[root] = pre[root] = 0;
117     same[root] = rev[root] = sum[root] = key[root] = 0;
118     lx[root] = rx[root] = mx[root] = -INF;
119     NewNode(root,0,-1);
120     NewNode(ch[root][1],root,-1);
121     for(int i = 0;i < n;i++)
122         scanf("%d",&a[i]);
123     Build(Key_value,0,n-1,ch[root][1]);
124     push_up(ch[root][1]);
125     push_up(root);
126 }
127 //旋转,0为左旋,1为右旋
128 void Rotate(int x,int kind)
129 {
130     int y = pre[x];
131     push_down(y);
132     push_down(x);
133     ch[y][!kind] = ch[x][kind];
134     pre[ch[x][kind]] = y;
135     if(pre[y])
136         ch[pre[y]][ch[pre[y]][1]==y] = x;
137     pre[x] = pre[y];
138     ch[x][kind] = y;
139     pre[y] = x;
140     push_up(y);
141 }
142 //Splay调整,将r结点调整到goal下面
143 void Splay(int r,int goal)
144 {
145     push_down(r);
146     while(pre[r] != goal)
147     {
148         if(pre[pre[r]] == goal)
149         {
150             push_down(pre[r]);
151             push_down(r);
152             Rotate(r,ch[pre[r]][0] == r);
153         }
154         else
155         {
156             push_down(pre[pre[r]]);
157             push_down(pre[r]);
158             push_down(r);
159             int y = pre[r];
160             int kind = ch[pre[y]][0]==y;
161             if(ch[y][kind] == r)
162             {
163                 Rotate(r,!kind);
164                 Rotate(r,kind);
165             }
166             else
167             {
168                 Rotate(y,kind);
169                 Rotate(r,kind);
170             }
171         }
172     }
173     push_up(r);
174     if(goal == 0) root = r;
175 }
176 int Get_kth(int r,int k)
177 {
178     push_down(r);
179     int t = size[ch[r][0]] + 1;
180     if(t == k)return r;
181     if(t > k)return Get_kth(ch[r][0],k);
182     else return Get_kth(ch[r][1],k-t);
183 }
184 
185 //在第pos个数后面插入tot个数
186 void Insert(int pos,int tot)
187 {
188     for(int i = 0;i < tot;i++)scanf("%d",&a[i]);
189     Splay(Get_kth(root,pos+1),0);
190     Splay(Get_kth(root,pos+2),root);
191     Build(Key_value,0,tot-1,ch[root][1]);
192     push_up(ch[root][1]);
193     push_up(root);
194 }
195 
196 //删除子树
197 void erase(int r)
198 {
199     if(!r)return;
200     s[++tot2] = r;
201     erase(ch[r][0]);
202     erase(ch[r][1]);
203 }
204 //从第pos个数开始连续删除tot个数
205 void Delete(int pos,int tot)
206 {
207     Splay(Get_kth(root,pos),0);
208     Splay(Get_kth(root,pos+tot+1),root);
209     erase(Key_value);
210     pre[Key_value] = 0;
211     Key_value = 0;
212     push_up(ch[root][1]);
213     push_up(root);
214 }
215 //将从第pos个数开始的连续的tot个数修改为c
216 void Make_Same(int pos,int tot,int c)
217 {
218     Splay(Get_kth(root,pos),0);
219     Splay(Get_kth(root,pos+tot+1),root);
220     Update_Same(Key_value,c);
221     push_up(ch[root][1]);
222     push_up(root);
223 }
224 
225 //将第pos个数开始的连续tot个数进行反转
226 void Reverse(int pos,int tot)
227 {
228     Splay(Get_kth(root,pos),0);
229     Splay(Get_kth(root,pos+tot+1),root);
230     Update_Rev(Key_value);
231     push_up(ch[root][1]);
232     push_up(root);
233 }
234 //得到第pos个数开始的tot个数的和
235 int Get_Sum(int pos,int tot)
236 {
237     Splay(Get_kth(root,pos),0);
238     Splay(Get_kth(root,pos+tot+1),root);
239     return sum[Key_value];
240 }
241 //得到第pos个数开始的tot个数中最大的子段和
242 int Get_MaxSum(int pos,int tot)
243 {
244     Splay(Get_kth(root,pos),0);
245     Splay(Get_kth(root,pos+tot+1),root);
246     return mx[Key_value];
247 }
248 
249 void InOrder(int r)
250 {
251     if(!r)return;
252     push_down(r);
253     InOrder(ch[r][0]);
254     printf("%d ",key[r]);
255     InOrder(ch[r][1]);
256 }
257 
258 
259 
260 int main()
261 {
262     //freopen("in.txt","r",stdin);
263     //freopen("out.txt","w",stdout);
264      while(scanf("%d%d",&n,&q) == 2)   
265     {
266         Init();
267         char op[20];
268         int x,y,z;
269         while(q--)
270         {
271             scanf("%s",op);
272             if(strcmp(op,"INSERT") == 0)
273             {
274                 scanf("%d%d",&x,&y);
275                 Insert(x,y);
276             }
277             else if(strcmp(op,"DELETE") == 0)
278             {
279                 scanf("%d%d",&x,&y);
280                 Delete(x,y);
281             }
282             else if(strcmp(op,"MAKE-SAME") == 0)
283             {
284                 scanf("%d%d%d",&x,&y,&z);
285                 Make_Same(x,y,z);
286             }
287             else if(strcmp(op,"REVERSE") == 0)
288             {
289                 scanf("%d%d",&x,&y);
290                 Reverse(x,y);
291             }
292             else if(strcmp(op,"GET-SUM") == 0)
293             {
294                 scanf("%d%d",&x,&y);
295                 printf("%d\n",Get_Sum(x,y));
296             }
297             else if(strcmp(op,"MAX-SUM") == 0)
298                 printf("%d\n",Get_MaxSum(1,size[root]-2));
299         }
300     }
301     return 0;
302 }

 

 

 

 

 

 

posted on 2013-08-28 19:18  kuangbin  阅读(3386)  评论(0编辑  收藏  举报

导航

JAVASCRIPT: