1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 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
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
10
1
10
HINT
Source
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 ",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 ",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 ",Get_Sum(x,y)); 296 } 297 else if(strcmp(op,"MAX-SUM") == 0) 298 printf("%d ",Get_MaxSum(1,size[root]-2)); 299 } 300 } 301 return 0; 302 }