【题意】一圆环,有一个指针指着某个位置,初值指着1,按照顺时针方向计数。6种操作,插入数、区间加、询问点、区间翻转、删除点、指针移动。
【分析】破环为链,裸的Splay伸展树。
模板被我写挫了。


1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<algorithm> 5 6 using namespace std; 7 8 #define keyTree ch[ch[root][1]][0] 9 10 const int maxn = 510002; 11 12 int N, M, K1, K2; 13 int wh; 14 15 struct SplayTree 16 { 17 int sz[maxn]; 18 int ch[maxn][2]; 19 int pre[maxn]; 20 int root , top1 ; 21 22 void Rotate(int x,int f) 23 { 24 int y = pre[x]; 25 push_down(y); 26 push_down(x); 27 ch[y][!f] = ch[x][f]; 28 pre[ ch[x][f] ] = y; 29 pre[x] = pre[y]; 30 if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x; 31 ch[x][f] = y; 32 pre[y] = x; 33 push_up(y); 34 } 35 void Splay(int x,int goal) 36 { 37 push_down(x); 38 //puts("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); 39 while(pre[x] != goal) 40 { 41 int y = pre[x], z = pre[y]; 42 push_down(z); 43 push_down(y); 44 push_down(x); 45 if(pre[pre[x]] == goal) 46 { 47 Rotate(x , ch[pre[x]][0] == x); 48 } 49 else 50 { 51 int y = pre[x] , z = pre[y]; 52 int f = (ch[z][0] == y); 53 if(ch[y][f] == x) 54 { 55 Rotate(x , !f) , Rotate(x , f); 56 } 57 else 58 { 59 Rotate(y , f) , Rotate(x , f); 60 } 61 } 62 } 63 push_up(x); 64 if(goal == 0) root = x; 65 } 66 void RotateTo(int k,int goal) //把第k位的数转到goal下边 67 { 68 int x = root; 69 push_down(x); 70 while(sz[ ch[x][0] ] != k) 71 { 72 // printf("x = %d k = %d sz[x] = %d\n",x,k,sz[x]); 73 if(k < sz[ ch[x][0] ]) 74 { 75 x = ch[x][0]; 76 } 77 else 78 { 79 k -= (sz[ ch[x][0] ] + 1); 80 x = ch[x][1]; 81 } 82 push_down(x); 83 } 84 Splay(x,goal); 85 } 86 87 88 void debug() 89 { 90 printf("%d\n",root); 91 Treaval(root); 92 } 93 void Treaval(int x) 94 { 95 push_down(x); 96 if(x) 97 { 98 Treaval(ch[x][0]); 99 printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]); 100 Treaval(ch[x][1]); 101 } 102 } 103 104 105 void NewNode(int &x,int c) 106 { 107 x = ++top1; 108 ch[x][0] = ch[x][1] = pre[x] = 0; 109 sz[x] = 1; 110 111 val[x] = c;/*这是题目特定函数*/ 112 lazy[x] = 0; 113 add[x] = 0; 114 } 115 116 //把延迟标记推到孩子 117 void push_down(int x) /*这是题目特定函数*/ 118 { 119 int l = ch[x][0]; 120 int r = ch[x][1]; 121 if (lazy[x] != 0) 122 { 123 rev(l); 124 rev(r); 125 lazy[x] = 0; 126 } 127 if (add[x] != 0) 128 { 129 add[l] += add[x]; 130 add[r] += add[x]; 131 val[l] += add[x]; 132 val[r] += add[x]; 133 add[x] = 0; 134 } 135 } 136 //把孩子状态更新上来 137 void push_up(int x) 138 { 139 sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ]; 140 /*以下这是题目特定函数*/ 141 //um[x] = add[x] + val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ]; 142 } 143 144 /*初始化*/ 145 void makeTree(int &x,int l,int r,int f) 146 { 147 if(l > r) return ; 148 int m = (l + r)>>1; 149 NewNode(x , num[m]); /*num[m]权值改成题目所需的*/ 150 makeTree(ch[x][0] , l , m - 1 , x); 151 makeTree(ch[x][1] , m + 1 , r , x); 152 pre[x] = f; 153 push_up(x); 154 } 155 void init(int n) 156 { 157 ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0; 158 add[0] = sum[0] = 0; 159 160 NewNode(root , -1); 161 NewNode(ch[root][1] , -1); 162 pre[top1] = root; 163 sz[root] = 2; 164 165 cnt = n; 166 wh = 1; 167 168 169 for (int i=1; i<=n; i++) 170 { 171 scanf("%d",&num[i]); 172 } 173 makeTree(keyTree, 1, n, ch[root][1]); 174 push_up(ch[root][1]); 175 push_up(root); 176 //Treaval(root); 177 } 178 179 void rev(int x) 180 { 181 if (x == 0) 182 return ; 183 swap(ch[x][0], ch[x][1]); 184 lazy[x] ^= 1; 185 } 186 int query() 187 { 188 int k = wh; 189 int x = root; 190 push_down(x); 191 while (sz[ch[x][0]] != k) 192 { 193 //printf("x %d k %d %d\n",x,k,sz[ch[x][0]]); 194 if (k < sz[ch[x][0]]) 195 { 196 x = ch[x][0]; 197 } 198 else 199 { 200 k -= (sz[ch[x][0]] + 1); 201 x = ch[x][1]; 202 } 203 push_down(x); 204 } 205 //printf("x = %d\n",x); 206 return val[x]; 207 } 208 void add_value(int l,int r,int x) 209 { 210 RotateTo(l-1, 0); 211 RotateTo(r+1, root); 212 add[keyTree] += x; 213 val[keyTree] += x; 214 push_up(ch[root][1]); 215 push_up(root); 216 } 217 void update(int x) 218 { 219 int l, r; 220 if (wh + K2 - 1<=cnt) 221 { 222 l = wh; 223 r = wh + K2 - 1; 224 add_value(l,r,x); 225 } 226 else 227 { 228 l = wh; 229 r = cnt; 230 add_value(l,r,x); 231 232 l = 1; 233 r = (wh + K2 -1 - cnt); 234 add_value(l,r,x); 235 } 236 } 237 void hebin(int k,int s) 238 { 239 RotateTo(k-1, 0); 240 RotateTo(k, root); 241 242 keyTree = s; 243 pre[s] = ch[root][1]; 244 push_up(ch[root][1]); 245 push_up(root); 246 } 247 void insert(int x) 248 { 249 RotateTo(wh, 0); 250 RotateTo(wh+1,root); 251 NewNode(keyTree, x); 252 pre[keyTree] = ch[root][1]; 253 push_up(ch[root][1]); 254 push_up(root); 255 256 cnt++; 257 } 258 void dele() 259 { 260 RotateTo(wh-1, 0); 261 RotateTo(wh+1, root); 262 keyTree = 0; 263 push_up(ch[root][1]); 264 push_up(root); 265 266 if (wh == cnt) 267 { 268 wh = 1; 269 } 270 cnt--; 271 } 272 void move(int x) 273 { 274 if (x == 1) 275 { 276 wh--; 277 } 278 else 279 { 280 wh++; 281 } 282 if (wh==0) 283 { 284 wh = cnt; 285 } 286 if (wh == cnt+1) 287 { 288 wh = 1; 289 } 290 } 291 void lz(int l, int r) 292 { 293 RotateTo(l-1, 0); 294 RotateTo(r+1, root); 295 rev(keyTree); 296 } 297 void fanzhuan() 298 { 299 if (wh + K1-1 <=cnt) 300 { 301 lz(wh, wh + K1 - 1); 302 } 303 else 304 { 305 int p1, p2 , p3, p4; 306 p4 = cnt; 307 p1 = wh + K1 -1 - cnt; 308 p2 = split(1, p1); 309 wh = wh - p1; 310 p4 = p4 - p1; 311 hebin(p4+1, p2); 312 p1 = wh + K1 - 1; 313 lz(wh, p1); 314 } 315 } 316 int split(int l, int r) 317 { 318 RotateTo(l-1, 0); 319 RotateTo(r+1, root); 320 int res = keyTree; 321 keyTree = 0; 322 push_up(ch[root][1]); 323 push_up(root); 324 return res; 325 } 326 int cnt; 327 int val[maxn]; 328 int sum[maxn]; 329 int add[maxn]; 330 int num[maxn]; 331 int lazy[maxn]; 332 } spt; 333 334 int main() 335 { 336 char str[20]; 337 int x; 338 int cast = 0; 339 while (scanf("%d%d%d%d", &N,&M,&K1,&K2)) 340 { 341 if (N == 0 && M==0) 342 break; 343 spt.init(N); 344 printf("Case #%d:\n",++cast); 345 346 while (M--) 347 { 348 scanf("%s",str); 349 if (str[0] == 'a') 350 { 351 scanf("%d",&x); 352 spt.update(x); 353 } 354 else if (str[0] == 'r') 355 { 356 spt.fanzhuan(); 357 } 358 else if (str[0] == 'i') 359 { 360 scanf("%d",&x); 361 spt.insert(x); 362 } 363 else if (str[0] == 'd') 364 { 365 spt.dele(); 366 } 367 else if (str[0] == 'm') 368 { 369 scanf("%d",&x); 370 spt.move(x); 371 } 372 else 373 { 374 int ans = spt.query(); 375 printf("%d\n",ans); 376 } 377 } 378 } 379 return 0; 380 }
666

被折叠的 条评论
为什么被折叠?



