标签:bzoj bzoj1493 splay noi2007 伸展树
题目大意:有一个很长的带颜色的项链,要求你快速的维护一种数据结构,他可以:
1.把序列的后k个放在前面。
2.将区间2~cnt的珠子翻转。
3.将位置i和位置j的珠子互换。
4.将区间i到j染色成k
5.输出整个序列的颜色块的个数
6.输出从i到j的颜色块的个数。
思路:Splay。有些不好处理的是要时刻想着这是一个环,所以所有的计算颜色块的个数的时候要考虑收尾的颜色是否相同。还有从序列的尾部到转一圈回去的情况。
就因为这个题我的代码有个小小小小的问题,花了仨小时的时间带着数据才把错找到。。简直不知道说些什么好。。啊啊啊啊以后写题一定要细致啊!!!
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 500010 using namespace std; struct Complex{ int col,cnt_col,l_col,r_col; int size; Complex *son[2],*father; bool reverse,change; int change_into; void Combine(Complex *a,bool dir) { son[dir] = a; a->father = this; } bool Check() { return father->son[1] == this; } void Reverse(); void Paint(int val); void PushUp(); void PushDown(); }*nil = new Complex(),*root; int cnt,cols,asks; int src[MAX]; char cmd[10]; void Pretreatment(); inline Complex *NewComplex(int val); Complex *BuildTree(int l,int r); Complex *Kth(Complex *a,int k); inline void Rotate(Complex *a,bool dir); inline void Splay(Complex *a,Complex *aim); inline void SplaySeg(int x,int y); int main() { Pretreatment(); cin >> cnt >> asks; for(int i = 1;i <= cnt; ++i) scanf("%d",&src[i]); root = BuildTree(0,cnt + 1); root->father = nil; cin >> asks; for(int x,y,z,i = 1;i <= asks; ++i) { scanf("%s",cmd); if(cmd[0] == 'R') { scanf("%d",&x); SplaySeg(cnt - x + 1,cnt); Complex *temp = root->son[1]->son[0]; temp->father = nil; root->son[1]->son[0] = nil; root->son[1]->PushUp(),root->PushUp(); Splay(Kth(root,1),nil); Splay(Kth(root,2),root); root->son[1]->Combine(temp,false); } else if(cmd[0] == 'F') { SplaySeg(2,cnt); root->son[1]->son[0]->Reverse(); } else if(cmd[0] == 'S') { scanf("%d%d",&x,&y); if(x == y) continue; if(x > y) swap(x,y); Splay(Kth(root,x + 1),nil); Splay(Kth(root,y + 1),root); int temp = root->son[1]->col; root->son[1]->col = root->col; root->son[1]->PushUp(),root->PushUp(); root->col = temp; } else if(cmd[0] == 'P') { scanf("%d%d%d",&x,&y,&z); if(y >= x) { SplaySeg(x,y); root->son[1]->son[0]->Paint(z); } else { SplaySeg(x,cnt); root->son[1]->son[0]->Paint(z); root->son[1]->PushUp(),root->PushUp(); SplaySeg(1,y); root->son[1]->son[0]->Paint(z); } } else if(cmd[0] == 'C' && cmd[1] == '\0') { SplaySeg(1,cnt); int ans = root->son[1]->son[0]->cnt_col; ans -= (root->son[1]->son[0]->l_col == root->son[1]->son[0]->r_col); if(!ans) ++ans; printf("%d\n",ans); continue; } else { scanf("%d%d",&x,&y); if(y >= x) { SplaySeg(x,y); printf("%d\n",root->son[1]->son[0]->cnt_col); } else { int ans = 0; SplaySeg(x,cnt); ans = root->son[1]->son[0]->cnt_col; SplaySeg(1,y); ans += root->son[1]->son[0]->cnt_col; SplaySeg(1,cnt); ans -= (root->son[1]->son[0]->l_col == root->son[1]->son[0]->r_col); printf("%d\n",ans); } continue; } root->son[1]->PushUp(),root->PushUp(); } return 0; } void Complex:: Reverse() { if(!col) return ; reverse ^= 1; swap(son[0],son[1]); swap(l_col,r_col); } void Complex:: Paint(int val) { if(!col) return ; change = true; change_into = val; l_col = r_col = col = val; cnt_col = 1; } void Complex:: PushUp() { if(this == nil) return ; size = son[0]->size + son[1]->size + 1; if(!col) return ; cnt_col = 1; l_col = r_col = col; if(son[0]->col) { cnt_col += son[0]->cnt_col - (son[0]->r_col == col); l_col = son[0]->l_col; } if(son[1]->col) { cnt_col += son[1]->cnt_col - (son[1]->l_col == col); r_col = son[1]->r_col; } } void Complex:: PushDown() { if(this == nil) return ; if(reverse) { son[0]->Reverse(); son[1]->Reverse(); reverse = false; } if(change) { son[0]->Paint(change_into); son[1]->Paint(change_into); change = false; } } void Pretreatment() { nil->size = 0; nil->col = nil->l_col = nil->r_col = 0; nil->cnt_col = 0; nil->father = nil->son[0] = nil->son[1] = nil; } inline Complex *NewComplex(int val) { Complex *re = new Complex(); re->col = re->l_col = re->r_col = val; re->size = 1; if(val) re->cnt_col = 1; re->son[0] = re->son[1] = nil; return re; } Complex *BuildTree(int l,int r) { if(l > r) return nil; int mid = (l + r) >> 1; Complex *re = NewComplex(src[mid]); re->Combine(BuildTree(l,mid - 1),false); re->Combine(BuildTree(mid + 1,r),true); re->PushUp(); return re; } Complex *Kth(Complex *a,int k) { a->PushDown(); if(a->son[0]->size >= k) return Kth(a->son[0],k); k -= a->son[0]->size; if(k == 1) return a; return Kth(a->son[1],k - 1); } inline void Rotate(Complex *a,bool dir) { Complex *f = a->father; f->PushDown(),a->PushDown(); f->son[!dir] = a->son[dir]; f->son[!dir]->father = f; a->son[dir] = f; a->father = f->father; f->father->son[f->Check()] = a; f->father = a; f->PushUp(); if(root == f) root = a; } inline void Splay(Complex *a,Complex *aim) { while(a->father != aim) { if(a->father->father == aim) Rotate(a,!a->Check()); else if(!a->father->Check()) { if(!a->Check()) Rotate(a->father,true),Rotate(a,true); else Rotate(a,false),Rotate(a,true); } else { if(a->Check()) Rotate(a->father,false),Rotate(a,false); else Rotate(a,true),Rotate(a,false); } } a->PushUp(); } inline void SplaySeg(int x,int y) { x++,y++; Splay(Kth(root,x - 1),nil); Splay(Kth(root,y + 1),root); }
标签:bzoj bzoj1493 splay noi2007 伸展树
原文地址:http://blog.csdn.net/jiangyuze831/article/details/39552621