题意:维护一个圈,实现六个功能,给某位置起的一些数增加某值,反转某一段数,添加删除某些数,移动当前所指的位置,
简单的splay,把圈拆成链,对于每种操作,处理一下。
#define inf 0x3f3f3f3f #define keyTree (ch[ ch[root][1] ][0]) const int maxn = 222222; struct SplayTree { int sz[maxn]; int ch[maxn][2]; int pre[maxn]; int root , top1 , top2; int ss[maxn] , que[maxn]; void Rotate(int x,int f) { int y = pre[x]; push_down(y); push_down(x); ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x; ch[x][f] = y; pre[y] = x; push_up(y); } void Splay(int x,int goal) { push_down(x); //puts("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); while(pre[x] != goal) { int y = pre[x], z = pre[y]; push_down(z); push_down(y); push_down(x); if(pre[pre[x]] == goal) { Rotate(x , ch[pre[x]][0] == x); } else { int y = pre[x] , z = pre[y]; int f = (ch[z][0] == y); if(ch[y][f] == x) { Rotate(x , !f) , Rotate(x , f); } else { Rotate(y , f) , Rotate(x , f); } } } push_up(x); if(goal == 0) root = x; } void RotateTo(int k,int goal) {//把第k位的数转到goal下边 int x = root; push_down(x); while(sz[ ch[x][0] ] != k) { // printf("x = %d k = %d sz[x] = %d ",x,k,sz[x]); if(k < sz[ ch[x][0] ]) { x = ch[x][0]; } else { k -= (sz[ ch[x][0] ] + 1); x = ch[x][1]; } push_down(x); } Splay(x,goal); } //以上一般不修改////////////////////////////////////////////////////////////////////////////// void debug() { printf("%d ",root); Treaval(root); } void Treaval(int x) { push_down(x); if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d ",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]); Treaval(ch[x][1]); } } //以上Debug //以下是题目的特定函数: void NewNode(int &x,int c) { x = ++top1; ch[x][0] = ch[x][1] = pre[x] = 0; sz[x] = 1; val[x] = c; lazy[x] = add[x] = 0 ; } //把延迟标记推到孩子 void push_down(int x) { if(lazy[x] != 0 ) { rev(ch[x][0]); rev(ch[x][1]); //swap(add[ch[x][0]],add[ch[x][1]]); lazy[x] = 0 ; } if(add[x] != 0 ) { val[ch[x][0]] += add[x]; val[ch[x][1]] += add[x]; add[ch[x][0]] += add[x]; add[ch[x][1]] += add[x]; add[x] = 0 ; } return ; } //把孩子状态更新上来 void push_up(int x) { sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ]; } /*初始化*/ void makeTree(int &x,int l,int r,int f) { if(l > r) return ; int m = (l + r)>>1; NewNode(x , num[m]); /*num[m]权值改成题目所需的*/ makeTree(ch[x][0] , l , m - 1 , x); makeTree(ch[x][1] , m + 1 , r , x); pre[x] = f; push_up(x); } void clear() { cnt = 0 ; ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0; add[0] = lazy[0] = 0 ; root = top1 = 0; //为了方便处理边界,加两个边界顶点 NewNode(root , -inf); NewNode(ch[root][1] , inf); pre[top1] = root; sz[root] = 2; } void init(int pos,int n) { clear(); cnt = n; RotateTo(pos , 0 ); RotateTo(pos + 1, root); makeTree(keyTree , 1 , n , ch[root][1]); push_up(ch[root][1]); push_up(root); } void update(int u,int v,int _add ) { RotateTo(u - 1 , 0 ); RotateTo(v + 1, root ); add[keyTree] += _add; val[keyTree] += _add; push_up(root); //Splay(keyTree,root); } void rev(int x) { if(x == 0 ) return; swap(ch[x][0] ,ch[x][1]); lazy[x] ^= 1; } void lz(int u,int v ) { RotateTo(u - 1 , 0 ); RotateTo(v + 1 , root ); rev(keyTree); //Splay(keyTree,root); } int split(int u,int v ) { RotateTo(u - 1 , 0 ); RotateTo(v + 1 , root ); int res = keyTree; keyTree = 0 ; push_up(ch[root][1]); push_up(root); return res ; } void hb(int k,int ts) { RotateTo(k - 1 ,0 ); RotateTo(k , root); keyTree = ts ; pre[ts] = ch[root][1]; push_up(ch[root][1]); push_up(root); } void insert(int k,int val) { cnt ++ ; RotateTo(k - 1 , 0 ); RotateTo(k , root ) ; NewNode(keyTree,val); pre[keyTree] = ch[root][1]; push_up(ch[root][1]); push_up(root); } int getkth(int k ) { int x = root ; push_down(x); while(sz[ ch[x][0] ] != k) { // printf("x = %d k = %d sz[x] = %d ",x,k,sz[x]); if(k < sz[ ch[x][0] ]) { x = ch[x][0]; } else { k -= (sz[ ch[x][0] ] + 1); x = ch[x][1]; } push_down(x); } return val[x]; } void del(int k) { RotateTo(k - 1 , 0); RotateTo(k + 1 , root); //printf("val = %d ",val[keyTree]); //printf("sz = %d ",sz[keyTree]); cnt -- ; keyTree = 0 ; push_up(ch[root][1]); push_up(root); // erase(keyTree); } int cnt ; /*这是题目特定变量*/ int num[maxn]; int val[maxn]; int add[maxn]; int lazy[maxn]; } spt; int n,m,k1,k2; int wh; int main() { int cas; cas = 0 ; char str[10]; while( scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF && !(n == 0 && m == 0 && k1 == 0 && k2 == 0 ) ) { for(int i =1 ; i<= n ; i ++ ) scanf("%d",&spt.num[i]); spt.init(0,n); wh = 1 ; printf("Case #%d: ",++cas); int x; while(m -- ) { scanf("%s",str); if( str[0] == 'q' ) { int ans = spt.getkth(wh); printf("%d ",ans); } else if( str[0] == 'r' ) { if(wh + k1 - 1 <= spt.cnt) { spt.lz(wh , wh + k1 - 1); } else { int p1,p2,p3,p4; p4 = spt.cnt; p1 = wh + k1 - 1 - spt.cnt; p2 = spt.split(1,p1); wh = wh - p1; p4 = p4 - p1; spt.hb(p4 + 1 ,p2); p1 = wh + k1 - 1 ; spt.lz(wh,p1); } } else if(str[0] == 'i') { scanf("%d",&x); spt.insert(wh + 1 ,x); } else if(str[0] == 'm') { scanf("%d",&x); if(x == 1 ) { wh -- ; if(wh == 0 ) wh = spt.cnt; } else { wh ++ ; if(wh >spt.cnt) wh = 1; } } else if(str[0] == 'd') { if(wh == spt.cnt) { spt.del(wh); wh = 1; } else { spt.del(wh); } } else if(str[0] == 'a') { scanf("%d",&x); int p1,p2,p3,lef; if(wh + k2 - 1 <= spt.cnt) { spt.update(wh,wh + k2 - 1 ,x); } else { lef = wh + k2 - 1 - spt.cnt; // printf("%d %d ",k2,lef); spt.update(1,lef,x); spt.update(wh,spt.cnt,x); } } // spt.debug(); } } return 0; }
7k+的代码,居然调出来了,好开心。