新学的,其实吧,就那么回事....
看了几天,splay处理序列问题,真的非常厉害,翻转,插入,删除,线段树实现不了的功能,splay用起来很方便。
这题基本就是检验模板的题,各种操作都有,错了好多次,发现以前写的代码有错了的,数据水点,给水过了,注意pushup。
Splay模板
#include <cstdio> #include <cstring> #include <map> #include <algorithm> #include <iostream> using namespace std; #define N 500000 #define INF 0x7FFFFFFF #define keyTree (ch[ ch[root][1] ][0]) int pre[N]; int lz[N]; int rev[N]; int ch[N][2]; int val[N]; int minz[N]; int sz[N]; int num[N]; int root,t; void pushup(int x) { minz[x] = min(val[x],min(minz[ch[x][0]],minz[ch[x][1]])); sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1; } void Update_Rev(int x) { if(!x) return ; swap(ch[x][1],ch[x][0]); rev[x] ^= 1; } void Update_Add(int x,int d) { if(!x) return ; val[x] += d; minz[x] += d; lz[x] += d; } void pushdown(int x) { if(lz[x]) { Update_Add(ch[x][0],lz[x]); Update_Add(ch[x][1],lz[x]); lz[x] = 0; } if(rev[x]) { Update_Rev(ch[x][0]); Update_Rev(ch[x][1]); rev[x] = 0; } } void NewNode(int &x,int c) { x = ++t; ch[x][0] = ch[x][1] = 0; sz[x] = 1; lz[x] = rev[x] = 0; minz[x] = val[x] = c; } void makeTree(int &x,int l,int r,int rt) { if(l > r) return ; int m; m = (l + r)>>1; NewNode(x,num[m]); makeTree(ch[x][0],l,m-1,x); makeTree(ch[x][1],m+1,r,x); pre[x] = rt; pushup(x); } void Rotate(int x,int flag)//左旋 右旋 { int y = pre[x]; pushdown(y); pushdown(x); ch[y][!flag] = ch[x][flag]; pre[ch[x][flag]] = y; pre[x] = pre[y]; if(pre[x]) ch[pre[y]][ ch[pre[y]][1] == y] = x; ch[x][flag] = y; pre[y] = x; pushup(y); } void splay(int x,int goal)//把x转到goal下面 { int y,z,flag; while(pre[x] != goal) { if(pre[pre[x]] == goal) { pushdown(pre[x]); pushdown(x); Rotate(x,ch[pre[x]][0] == x); } else { y = pre[x]; z = pre[y]; pushdown(z); pushdown(y); pushdown(x); flag = (ch[z][0] == y); if(ch[y][flag] == x) { Rotate(x,!flag); Rotate(x,flag); } else { Rotate(y,flag); Rotate(x,flag); } } } pushup(x); if(goal == 0) root = x; } void RotateTo(int k,int goal)//将第k个,转到goal下面 { int x = root; pushdown(x); while(sz[ch[x][0]] != k) { if(k < sz[ch[x][0]]) { x = ch[x][0]; } else { k -= (sz[ch[x][0]] + 1); x = ch[x][1]; } pushdown(x); } splay(x,goal); } void init(int n) { root = t = 0; ch[0][0] = ch[0][1] = lz[0] = pre[0] = 0; val[0] = minz[0] = 0; rev[0] = sz[0] = 0;//初始化 NewNode(root,-1); NewNode(ch[root][1],-1); pre[t] = root; int i; for(i = 0; i < n; i ++) { scanf("%d",&num[i]); } makeTree(keyTree,0,n-1,ch[root][1]);//建树 pushup(ch[root][1]); pushup(root); } int main() { int n,i,x,y,d,m; char str[101]; scanf("%d",&n); init(n); scanf("%d",&m); for(i = 0; i < m; i ++) { scanf("%s",str); if(strcmp(str,"ADD") == 0) { scanf("%d%d%d",&x,&y,&d); RotateTo(x-1,0); RotateTo(y+1,root); Update_Add(keyTree,d); pushup(ch[root][1]); pushup(root); } else if(strcmp(str,"INSERT") == 0)//插入 { scanf("%d%d",&x,&y); RotateTo(x,0); RotateTo(x+1,root); NewNode(keyTree,y); pre[keyTree] = ch[root][1]; pushup(ch[root][1]); pushup(root); } else if(strcmp(str,"DELETE") == 0)//删除 { scanf("%d",&x); RotateTo(x-1,0); RotateTo(x+1,root); pre[keyTree] = 0; keyTree = 0; pushup(ch[root][1]); pushup(root); } else if(strcmp(str,"MIN") == 0)//最值 { scanf("%d%d",&x,&y); RotateTo(x-1,0); RotateTo(y+1,root); printf("%d\n",minz[keyTree]); } else if(strcmp(str,"REVOLVE") == 0)//右移t位 { int t,temp; scanf("%d%d%d",&x,&y,&t); if(x > y) swap(x,y); t = t%(y-x+1); if(t < 0) t += (y-x+1); if(t == 0) continue; RotateTo(y-t,0); RotateTo(y+1,root); temp = keyTree; keyTree = 0; RotateTo(x-1,0); RotateTo(x,root); keyTree = temp; pre[keyTree] = ch[root][1]; pushup(ch[root][1]); pushup(root); } else { scanf("%d%d",&x,&y);//翻转区间 if(x > y) swap(x,y); RotateTo(x-1,0); RotateTo(y+1,root); Update_Rev(keyTree); pushup(ch[root][1]); pushup(root); } } return 0; }
这题是现场赛的题目啊...非常麻烦,不过想好了,就没什么了,主要是翻转哪里。
#include <cstdio> #include <cstring> #include <map> #include <algorithm> #include <iostream> using namespace std; #define N 300000 #define INF 0x7FFFFFFF #define keyTree (ch[ ch[root][1] ][0]) int ch[N][2]; int pre[N]; int val[N]; int lz[N]; int sz[N]; int rev[N]; int num[N]; int root,t; void Update_Add(int x,int d) { if(!x) return ; lz[x] += d; val[x] += d; } void Update_Rev(int x) { if(!x) return ; swap(ch[x][0],ch[x][1]); rev[x] ^= 1; } void pushdown(int x) { if(lz[x]) { Update_Add(ch[x][0],lz[x]); Update_Add(ch[x][1],lz[x]); lz[x] = 0; } if(rev[x]) { Update_Rev(ch[x][0]); Update_Rev(ch[x][1]); rev[x] = 0; } } void pushup(int x) { sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1; } void NewNode(int &x,int c,int fa) { x = ++t; ch[x][0] = ch[x][1] = 0; lz[x] = rev[x] = 0; sz[x] = 1; val[x] = c; pre[x] = fa; } void makeTree(int &x,int l,int r,int rt) { if(l > r) return ; int m = (l + r)>>1; NewNode(x,num[m],rt); makeTree(ch[x][0],l,m-1,x); makeTree(ch[x][1],m+1,r,x); pushup(x); } void Rotate(int x,int flag) { int y = pre[x]; pushdown(y); pushdown(x); ch[y][!flag] = ch[x][flag]; pre[ch[x][flag]] = y; pre[x] = pre[y]; if(pre[x]) ch[pre[y]][ ch[pre[y]][1] == y ] = x; ch[x][flag] = y; pre[y] = x; pushup(y); } void splay(int x,int goal) { int y,z,flag; while(pre[x] != goal) { if(pre[pre[x]] == goal) { pushdown(pre[x]); pushdown(x); Rotate(x,ch[pre[x]][0] == x); } else { y = pre[x]; z = pre[y]; pushdown(z); pushdown(y); pushdown(x); flag = (ch[z][0] == y); if(ch[y][flag] == x) { Rotate(x,!flag); Rotate(x,flag); } else { Rotate(y,flag); Rotate(x,flag); } } } pushup(x); if(goal == 0) root = x; } void RotateTo(int k,int goal) { int x = root; pushdown(x); while(sz[ch[x][0]] != k) { if(k < sz[ch[x][0]]) { x = ch[x][0]; } else { k -= (sz[ch[x][0]] + 1); x = ch[x][1]; } pushdown(x); } splay(x,goal); } int get_kth(int k) { int x = root; pushdown(x); while(sz[ch[x][0]] != k) { if(k < sz[ch[x][0]]) { x = ch[x][0]; } else { k -= (sz[ch[x][0]] + 1); x = ch[x][1]; } pushdown(x); } return val[x]; } void show(int x) { if(x == 0) return ; pushdown(x); show(ch[x][0]); if(val[x] > 0) { printf("%d ",val[x]); } show(ch[x][1]); } int main() { int i,k1,k2,n,m,pos,x,y,d,cas = 1; char str[100]; while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF) { if(n == 0&&m == 0) break; root = t = 0; ch[0][0] = ch[0][1] = sz[0] = pre[0] = 0; rev[0] = lz[0] = 0; NewNode(root,-1,0); NewNode(ch[root][1],-1,root); for(i = 0;i < n;i ++) scanf("%d",&num[i]); makeTree(keyTree,0,n-1,ch[root][1]); pushup(ch[root][1]); pushup(root); pos = 1; printf("Case #%d:\n",cas++); for(i = 0;i < m;i ++) { scanf("%s",str); if(str[0] == 'a') { scanf("%d",&d); x = pos; y = pos + k2 -1; if(y <= n) { RotateTo(x-1,0); RotateTo(y+1,root); Update_Add(keyTree,d); pushup(ch[root][1]); pushup(root); } else { RotateTo(x-1,0); RotateTo(n+1,root); Update_Add(keyTree,d); pushup(ch[root][1]); pushup(root); RotateTo(0,0); RotateTo(y-n+1,root); Update_Add(keyTree,d); pushup(ch[root][1]); pushup(root); } } else if(str[0] == 'r') { x = pos; y = pos + k1 - 1; if(y <= n) { RotateTo(x-1,0); RotateTo(y+1,root); Update_Rev(keyTree); } else { int tb = n-x+1; int ta = k1 - tb; RotateTo(x-1,0); RotateTo(n+1,root); Update_Rev(keyTree); pushup(ch[root][1]); pushup(root); RotateTo(0,0); RotateTo(ta+1,root); Update_Rev(keyTree); int temp = keyTree; keyTree = 0; pushup(ch[root][1]); pushup(root); RotateTo(x-1-ta,0); RotateTo(x-ta,root); keyTree = temp; pre[keyTree] = ch[root][1]; pushup(ch[root][1]); pushup(root); RotateTo(n-ta,0); RotateTo(n+1,root); temp = keyTree; keyTree = 0; pushup(ch[root][1]); pushup(root); RotateTo(0,0); RotateTo(1,root); keyTree = temp; pre[keyTree] = ch[root][1]; pushup(ch[root][1]); pushup(root); } } else if(str[0] == 'i') { n ++; scanf("%d",&d); x = pos; RotateTo(x,0); RotateTo(x+1,root); NewNode(keyTree,d,ch[root][1]); pushup(ch[root][1]); pushup(root); } else if(str[0] == 'd') { x = pos; RotateTo(x-1,0); RotateTo(x+1,root); keyTree = 0; pushup(ch[root][1]); pushup(root); if(pos == n) pos = 1; n --; } else if(str[0] == 'm') { scanf("%d",&d); if(d == 2) { pos ++; if(pos > n) pos = 1; } else { pos --; if(pos == 0) pos = n; } } else { printf("%d\n",get_kth(pos)); } } } return 0; } /* 5 100 3 2 1 2 3 4 5 m 2 m 2 m 2 reverse */