题意:
n个数字一开始排成一串 有两个指针L和R 指向了这串数字的一个区间的端点 现在有7种操作
1、使一个指针左移
2、使一个指针右移
3、在L后插入一个数字X
4、在R前插入一个数字X
5、删除L所指元素
6、删除R所指元素
7、翻转[L,R]区间
问 m次操作后 整串数字是什么样的
思路:
splay经典维护区间的操作 区间更新(翻转操作) 删除节点 插入节点
和 http://blog.csdn.net/houserabbit/article/details/37901199 这道Sort的题目类似 有区间翻转一定要注意down的操作
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; #define keytree ch[ch[root][1]][0] #define L(x) ch[x][0] #define R(x) ch[x][1] #define N 1000100 int t,n,m,tot,root; int a[N],ch[N][2],pre[N],size[N],val[N],rev[N]; void newnode(int &u,int fa,int w) { u=++tot; L(u)=R(u)=0; pre[u]=fa; size[u]=1; val[u]=w; rev[u]=0; } void up(int u) { size[u]=size[L(u)]+size[R(u)]+1; } void down(int u) { if(rev[u]) { rev[L(u)]^=1; rev[R(u)]^=1; rev[u]=0; swap(L(u),R(u)); } } void rotate(int u,int kind) { int fa=pre[u]; down(fa); down(u); ch[fa][!kind]=ch[u][kind]; pre[ch[u][kind]]=fa; if(pre[fa]) ch[pre[fa]][ch[pre[fa]][1]==fa]=u; pre[u]=pre[fa]; ch[u][kind]=fa; pre[fa]=u; up(fa); } void splay(int u,int goal) { int fa,kind; down(u); while(pre[u]!=goal) { if(pre[pre[u]]==goal) { down(pre[u]); down(u); rotate(u,L(pre[u])==u); } else { fa=pre[u]; down(pre[fa]); down(fa); down(u); kind=L(pre[fa])==fa; if(ch[fa][kind]==u) { rotate(u,!kind); rotate(u,kind); } else { rotate(fa,kind); rotate(u,kind); } } } up(u); if(goal==0) root=u; } int getkth(int u,int k) { down(u); int s=size[L(u)]+1; if(s==k) return u; if(s>k) return getkth(L(u),k); else return getkth(R(u),k-s); } void build(int &u,int l,int r,int fa) { if(l>r) return ; int mid=(l+r)>>1; newnode(u,fa,a[mid]); build(L(u),l,mid-1,u); build(R(u),mid+1,r,u); up(u); } void init() { root=tot=0; L(root)=R(root)=pre[root]=size[root]=val[root]=rev[root]=0; newnode(root,0,-1); newnode(R(root),root,-1); build(keytree,1,n,R(root)); up(R(root)); up(root); } int getpre(int u) { down(u); u=L(u); down(u); while(R(u)) { u=R(u); down(u); } return u; } void remove() { if(L(root)) { int i=getpre(root); splay(i,root); R(i)=R(root); pre[R(root)]=i; root=L(root); pre[root]=0; up(root); } else { root=R(root); pre[root]=0; } } int output=0; void inorder(int u) { down(u); if(L(u)) inorder(L(u)); if(u!=1&&u!=2) { if(output) putchar(' '); else output=1; printf("%d",val[u]); } if(R(u)) inorder(R(u)); } int main() { //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); int i,left,right; char op[20]; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d%d",&left,&right); init(); scanf("%d",&m); while(m--) { scanf("%s",op); if(strcmp(op,"MoveLeft")==0) { scanf("%s",op); if(op[0]=='L') left--; else right--; } else if(strcmp(op,"MoveRight")==0) { scanf("%s",op); if(op[0]=='L') left++; else right++; } else if(strcmp(op,"Insert")==0) { scanf("%s%d",op,&i); if(op[0]=='L') { splay(getkth(root,left),0); splay(getkth(root,left+1),root); } else { splay(getkth(root,right+1),0); splay(getkth(root,right+2),root); } newnode(keytree,R(root),i); right++; } else if(strcmp(op,"Delete")==0) { scanf("%s",op); if(op[0]=='L') splay(getkth(root,left+1),0); else splay(getkth(root,right+1),0); remove(); right--; } else if(strcmp(op,"Reverse")==0) { splay(getkth(root,left),0); splay(getkth(root,right+2),root); rev[keytree]^=1; } } output=0; inorder(root); puts(""); } return 0; }
原文地址:http://blog.csdn.net/houserabbit/article/details/37996187