题目来源BZOJ1500
这题的思路:
1、这题的话,稍微会splay的人,一般前面四个都不是问题。。主要是最后的一个,要你在修改的同时要维护好最大字段和。。。
2、最大字段和其实就是区间合并。具体操作可以看POJ2750,这是这道题的简化版本。
3、然后这题就是三个区间合并嘛。。。慢慢讨论就好了。。。这题写了我一天的时间。。从吃完午饭一直写到了晚上8点才AC。。。
直接贴代码吧。。这题是我为了学LCT,所以想做做Splay的题先熟悉一下Splay。。。结果选了这个BOSS题。。。心理阴影。。。。
我觉得我pushup那段写的挺清楚的23333 思路可以看我的pushup和pushdown函数的代码,应该挺好懂的
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<stack> 5 6 using namespace std; 7 8 const int N=500005,INF=0x3f3f3f3f; 9 10 struct Splay_Tree 11 { 12 struct Node 13 { 14 int val,sum,cover,Size,son[2],mxl,mxr,mx; 15 bool rev,cov; 16 void init(int _val) 17 { 18 val=sum=mxl=mxr=mx=_val; 19 Size=1; 20 rev=cov=cover=son[0]=son[1]=0; 21 } 22 } T[N]; 23 stack<int>mem; 24 int fa[N],root,tot; 25 26 void pushDown(int x)///下放标记(序列操作) 27 { 28 if(x==0)return ; 29 if(T[x].cov) 30 { 31 if(T[x].son[0]) 32 { 33 T[T[x].son[0]].cov=1; 34 T[T[x].son[0]].cover=T[T[x].son[0]].val=T[x].cover; 35 T[T[x].son[0]].sum=T[x].cover*T[T[x].son[0]].Size; 36 T[T[x].son[0]].rev=0; 37 if(T[x].cover>=0) 38 T[T[x].son[0]].mx=T[T[x].son[0]].mxl=T[T[x].son[0]].mxr=T[x].cover*T[T[x].son[0]].Size; 39 else 40 T[T[x].son[0]].mx=T[T[x].son[0]].mxl=T[T[x].son[0]].mxr=T[x].cover; 41 } 42 if(T[x].son[1]) 43 { 44 T[T[x].son[1]].cov=1; 45 T[T[x].son[1]].cover=T[T[x].son[1]].val=T[x].cover; 46 T[T[x].son[1]].sum=T[x].cover*T[T[x].son[1]].Size; 47 T[T[x].son[1]].rev=0; 48 if(T[x].cover>=0) 49 T[T[x].son[1]].mx=T[T[x].son[1]].mxl=T[T[x].son[1]].mxr=T[x].cover*T[T[x].son[1]].Size; 50 else 51 T[T[x].son[1]].mx=T[T[x].son[1]].mxl=T[T[x].son[1]].mxr=T[x].cover; 52 } 53 T[x].cov=T[x].cover=T[x].rev=0; 54 } 55 if(T[x].rev) 56 { 57 if(T[x].son[0]) 58 { 59 T[T[x].son[0]].rev^=1; 60 swap(T[T[x].son[0]].mxl,T[T[x].son[0]].mxr); 61 } 62 if(T[x].son[1]) 63 { 64 T[T[x].son[1]].rev^=1; 65 swap(T[T[x].son[1]].mxl,T[T[x].son[1]].mxr); 66 } 67 swap(T[x].son[0],T[x].son[1]); 68 T[x].rev=0; 69 } 70 } 71 72 void pushUp(int x)///更新节点(序列操作) 73 { 74 T[x].Size=1; 75 T[x].sum=T[x].val; 76 if(T[x].son[0]) 77 T[x].sum+=T[T[x].son[0]].sum,T[x].Size+=T[T[x].son[0]].Size; 78 if(T[x].son[1]) 79 T[x].sum+=T[T[x].son[1]].sum,T[x].Size+=T[T[x].son[1]].Size; 80 81 if(T[x].son[0]&&T[x].son[1]) 82 { 83 T[x].mx=T[x].val; 84 T[x].mx=max(T[x].mx,T[T[x].son[0]].mx); 85 T[x].mx=max(T[x].mx,T[T[x].son[1]].mx); 86 T[x].mx=max(T[x].mx,T[T[x].son[0]].mxr+T[x].val+T[T[x].son[1]].mxl); 87 T[x].mx=max(T[x].mx,T[x].val+T[T[x].son[0]].mxr); 88 T[x].mx=max(T[x].mx,T[x].val+T[T[x].son[1]].mxl); 89 90 T[x].mxl=T[T[x].son[0]].mxl; 91 T[x].mxl=max(T[x].mxl,T[T[x].son[0]].sum+T[x].val); 92 T[x].mxl=max(T[x].mxl,T[T[x].son[0]].sum+T[x].val+T[T[x].son[1]].mxl); 93 94 T[x].mxr=T[T[x].son[1]].mxr; 95 T[x].mxr=max(T[x].mxr,T[T[x].son[1]].sum+T[x].val); 96 T[x].mxr=max(T[x].mxr,T[T[x].son[1]].sum+T[x].val+T[T[x].son[0]].mxr); 97 } 98 else if(T[x].son[0]&&!T[x].son[1]) 99 { 100 T[x].mx=max(T[T[x].son[0]].mxr+T[x].val,T[T[x].son[0]].mx); 101 102 T[x].mx=max(T[x].mx,T[x].val); 103 104 T[x].mxl=max(T[T[x].son[0]].mxl,T[T[x].son[0]].sum+T[x].val); 105 106 T[x].mxr=max(T[x].val,T[x].val+T[T[x].son[0]].mxr); 107 } 108 else if(!T[x].son[0]&&T[x].son[1]) 109 { 110 T[x].mx=max(T[T[x].son[1]].mxl+T[x].val,T[T[x].son[1]].mx); 111 112 T[x].mx=max(T[x].mx,T[x].val); 113 114 T[x].mxl=max(T[x].val,T[x].val+T[T[x].son[1]].mxl); 115 116 T[x].mxr=max(T[T[x].son[1]].mxr,T[T[x].son[1]].sum+T[x].val); 117 } 118 else T[x].mxl=T[x].mxr=T[x].mx=T[x].val; 119 120 } 121 122 /*inline void up(int x)///更新节点(普通平衡树操作) 123 { 124 T[x].Size=1; 125 if(T[x].son[0]) 126 T[x].Size+=T[T[x].son[0]].Size; 127 if(T[x].son[1]) 128 T[x].Size+=T[T[x].son[1]].Size; 129 }*/ 130 131 void Rotate(int x,int kind)///旋转,有左旋右旋(反正配合splay用就好了233) 132 { 133 int y=fa[x],z=fa[y]; 134 T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y; 135 T[x].son[kind]=y,fa[y]=x; 136 T[z].son[T[z].son[1]==y]=x,fa[x]=z; 137 pushUp(y); 138 } 139 140 void Splay(int x,int goal)///把下标为x的元素旋转到目标的儿子节点 141 { 142 if(x==goal)return ; 143 while(fa[x]!=goal) 144 { 145 int y=fa[x],z=fa[y]; 146 pushDown(z),pushDown(y),pushDown(x); 147 int rx=T[y].son[0]==x,ry=T[z].son[0]==y; 148 if(z==goal)Rotate(x,rx); 149 else 150 { 151 if(rx==ry)Rotate(y,ry); 152 else Rotate(x,rx); 153 Rotate(x,ry); 154 } 155 } 156 pushUp(x); 157 if(goal==0)root=x; 158 } 159 160 int Select(int pos)///查找第k小元素 161 { 162 pos--; 163 int u=root; 164 pushDown(u); 165 while(T[T[u].son[0]].Size!=pos) 166 { 167 if(pos<T[T[u].son[0]].Size)u=T[u].son[0]; 168 else 169 { 170 pos-=T[T[u].son[0]].Size+1; 171 u=T[u].son[1]; 172 } 173 pushDown(u); 174 } 175 return u; 176 } 177 178 179 void Reverse(int L,int R)///序列操作的区间翻转 180 { 181 if(L>R)return ; 182 int u=Select(L-1),v=Select(R+1); 183 Splay(u,0); 184 Splay(v,u); 185 T[T[v].son[0]].rev^=1; 186 swap(T[T[v].son[0]].mxl,T[T[v].son[0]].mxr); 187 pushDown(T[v].son[0]); 188 update(T[v].son[0]); 189 } 190 191 void Cover(int L,int R,int Val)///序列操作的区间翻转 192 { 193 if(L>R)return ; 194 int u=Select(L-1),v=Select(R+1); 195 Splay(u,0); 196 Splay(v,u); 197 T[T[v].son[0]].cov=1; 198 T[T[v].son[0]].cover=T[T[v].son[0]].val=Val; 199 pushDown(T[v].son[0]); 200 update(T[v].son[0]); 201 } 202 203 int build(int L,int R,int *a)///区间操作建树 204 { 205 if(L>R)return 0; 206 int mid=(L+R)>>1,sL,sR; 207 int loc=mem.top();mem.pop(); 208 T[loc].init(a[mid]); 209 if(L==R)return loc; 210 T[loc].son[0]=sL=build(L,mid-1,a); 211 T[loc].son[1]=sR=build(mid+1,R,a); 212 fa[sL]=fa[sR]=loc; 213 pushUp(loc); 214 return loc; 215 } 216 217 void init(int n,int *a)///区间操作,输入n个元素建树 218 { 219 T[0].init(INF); 220 for(int i=500001;i>=1;i--) 221 mem.push(i); 222 root=build(1,n,a),fa[root]=0; 223 fa[0]=0,T[0].son[1]=root,T[0].Size=0; 224 } 225 226 void Insert(int pos,int n,int *a) 227 { 228 if(n==0)return ; 229 int u=Select(pos-1),v=Select(pos); 230 Splay(u,0); 231 Splay(v,u); 232 fa[T[v].son[0]=build(1,n,a)]=v; 233 update(T[v].son[0]); 234 } 235 236 void Delete(int L,int R) 237 { 238 if(L>R)return ; 239 int u=Select(L-1),v=Select(R+1); 240 Splay(u,0); 241 Splay(v,u); 242 Free(T[v].son[0]); 243 T[v].son[0]=0; 244 update(v); 245 } 246 247 int Get_sum(int L,int R) 248 { 249 if(L>R)return 0; 250 int u=Select(L-1),v=Select(R+1); 251 Splay(u,0); 252 Splay(v,u); 253 if(T[v].son[0]) 254 return T[T[v].son[0]].sum; 255 else return 0; 256 } 257 258 int Get_max(int L,int R) 259 { 260 if(L>R)return 0; 261 int u=Select(L-1),v=Select(R+1); 262 Splay(u,0); 263 Splay(v,u); 264 if(T[v].son[0]) 265 return T[T[v].son[0]].mx; 266 else return 0; 267 } 268 269 void Free(int x) 270 { 271 if(x==0)return ; 272 Free(T[x].son[0]); 273 mem.push(x); 274 Free(T[x].son[1]); 275 } 276 277 /*void Insert(int &t,int val,int par=0)///普通平衡树,往某个地方的下面插入元素,一般是插入根节点 278 { 279 if(t==0) 280 { 281 t=++tot; 282 T[t].init(val); 283 fa[t]=par; 284 Splay(tot,0); 285 } 286 else 287 { 288 int cur=t; 289 if(val<T[t].val)Insert(T[t].son[0],val,cur); 290 //else if(val==T[t].val)return ; 291 else Insert(T[t].son[1],val,cur); 292 up(cur); 293 } 294 }*/ 295 296 /*int find(int t,int v)///普通平衡树查找值为v的元素 297 { 298 if(t==0)return 0; 299 else if(T[t].val==v) 300 { 301 Splay(t,0); 302 return t; 303 } 304 else if(v<T[t].val)return find(T[t].son[0],v); 305 else return find(T[t].son[1],v); 306 }*/ 307 308 ///删除根节点元素 309 /*void Delete() 310 { 311 if(!T[root].son[0]) 312 { 313 fa[T[root].son[1]]=0; 314 root=T[root].son[1]; 315 } 316 else 317 { 318 int cur=T[root].son[0]; 319 while(T[cur].son[1])cur=T[cur].son[1]; 320 Splay(cur,root); 321 T[cur].son[1]=T[root].son[1]; 322 root=cur,fa[cur]=0,fa[T[root].son[1]]=root; 323 up(root); 324 } 325 }*/ 326 327 int size() 328 { 329 return T[root].Size; 330 } 331 332 ///从t开始找值为v的前驱,返回值 333 int pred(int t,int v) 334 { 335 if(t==0)return v; 336 else 337 { 338 if(v<=T[t].val)return pred(T[t].son[0],v); 339 else 340 { 341 int ans=pred(T[t].son[1],v); 342 if(ans==v) 343 ans=T[t].val,Splay(t,0); 344 return ans; 345 } 346 } 347 } 348 ///查找下标t节点的前驱返回下标 349 int pred(int t) 350 { 351 Splay(t,0); 352 int u=T[t].son[0]; 353 if(u==0)return fa[t]; 354 while(T[u].son[1])u=T[u].son[1]; 355 return u; 356 } 357 358 ///从t开始找值为v的后继,返回值 359 int succ(int t,int v) 360 { 361 if(t==0)return v; 362 else 363 { 364 if(v>=T[t].val)return succ(T[t].son[1],v); 365 else 366 { 367 int ans=succ(T[t].son[0],v); 368 if(ans==v) 369 ans=T[t].val,Splay(t,0); 370 return ans; 371 } 372 } 373 } 374 375 ///查找下标t节点的后继返回下标 376 int succ(int t) 377 { 378 Splay(t,0); 379 int u=T[t].son[1]; 380 if(u==0)return fa[t]; 381 while(T[u].son[0])u=T[u].son[0]; 382 return u; 383 } 384 385 void Preorder( int t ){///输出成序列顺便检查是否有逻辑错误 386 if( !t ) return; 387 pushDown(t); 388 Preorder( T[t].son[0] ); 389 if(T[t].son[0]&&fa[T[t].son[0]]!=t) 390 printf("!"); 391 printf("%d " , T[t].val ); 392 Preorder( T[t].son[1] ); 393 } 394 395 /*void init()///普通平衡树初始化 396 { 397 T[0].init(-INF); 398 tot=root=0; 399 }*/ 400 401 void update(int x)///更新下标为x的节点。。手动操作后调用 402 { 403 while(x!=0) 404 pushUp(x),x=fa[x]; 405 } 406 407 }; 408 409 Splay_Tree tree; 410 411 int a[N]; 412 413 char str[22]; 414 415 int main() 416 { 417 int n,m; 418 scanf("%d%d",&n,&m); 419 for(int i=2;i<=n+1;i++) 420 scanf("%d",a+i); 421 tree.init(n+2,a); 422 int sum=n; 423 while(m--) 424 { 425 scanf("%s",str+1); 426 if(str[3]=='S') 427 { 428 int pos,tot; 429 scanf("%d%d",&pos,&tot); 430 pos++; 431 pos++; 432 sum+=tot; 433 for(int i=1;i<=tot;i++) 434 scanf("%d",a+i); 435 tree.Insert(pos,tot,a); 436 } 437 else if(str[3]=='L') 438 { 439 int pos,tot; 440 scanf("%d%d",&pos,&tot); 441 pos++; 442 tree.Delete(pos,pos+tot-1); 443 sum-=tot; 444 } 445 else if(str[3]=='K') 446 { 447 int pos,tot,cov; 448 scanf("%d%d%d",&pos,&tot,&cov); 449 pos++; 450 tree.Cover(pos,pos+tot-1,cov); 451 } 452 else if(str[3]=='V') 453 { 454 int pos,tot; 455 scanf("%d%d",&pos,&tot); 456 pos++; 457 tree.Reverse(pos,pos+tot-1); 458 } 459 else if(str[3]=='T') 460 { 461 int pos,tot; 462 scanf("%d%d",&pos,&tot); 463 pos++; 464 printf("%d\n",tree.Get_sum(pos,pos+tot-1)); 465 } 466 if(str[3]=='X') 467 { 468 printf("%d\n",tree.Get_max(2,tree.size()-1)); 469 } 470 } 471 return 0; 472 } 473