【题解】【HDU 3487】Play with Chain
简洁の题意:
有一个数列,有n个元素,从左到右依次为1,2,3…n。
有2种操作:
CUT a b c 把第a个元素到第b个元素取走,放在剩下的数列中的第c个元素后。
FILP a b 把区间a到b翻转。
给定m个操作,输出最后的数列。
百度了好久好像都是用splay做的啊QAQ
我根本不会打splay啊QAQ
于是我们果断放弃
我们不是还有FHQ_treap吗qwq
翻转操作见洛谷文艺平衡树
考虑CUT操作
首先,分离出x~y区间(都会的对吧)
然后合并1~x-1和y+1~n区间
分离1~c区间
插入x~y区间
合并
The end
调了30min的代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <ctime> #include <string> using namespace std; const int inf=2e9; int root; struct note { int val; int size; int rd; int tag; int ch[2]; }; struct fhq_treap { int cnt; note tree[100010]; inline void up(int o) { tree[o].size=tree[tree[o].ch[0]].size+tree[tree[o].ch[1]].size+1; } inline void down(int o) { if(!tree[o].tag||!o) { return; } tree[o].ch[0]^=tree[o].ch[1]^=tree[o].ch[0]^=tree[o].ch[1]; tree[tree[o].ch[0]].tag^=1; tree[tree[o].ch[1]].tag^=1; tree[o].tag=0; } void split(int x,int val,int &a,int &b) { if(!x) { a=b=0; return; } down(x); if(val>tree[tree[x].ch[0]].size) { a=x; split(tree[x].ch[1],val-tree[tree[x].ch[0]].size-1,tree[x].ch[1],b); } else { b=x; split(tree[x].ch[0],val,a,tree[x].ch[0]); } up(x); } int merge(int x,int y) { if((!x)||(!y)) { return x+y; } down(x); down(y); if(tree[x].rd<tree[y].rd) { tree[x].ch[1]=merge(tree[x].ch[1],y); up(x); return x; } else { tree[y].ch[0]=merge(x,tree[y].ch[0]); up(y); return y; } } inline int new_node(int val) { tree[++cnt].val=val; tree[cnt].size=1; tree[cnt].rd=rand(); return cnt; } inline void res(int x,int y) { int a,b,c,d; split(root,y,a,b); split(a,x-1,c,d); tree[d].tag^=1; root=merge(merge(c,d),b); } inline void cut(int x,int y,int pos) { int a,b,c,d; split(root,y,a,b); split(a,x-1,c,d); root=merge(c,b); int e,f; split(root,pos,e,f); root=merge(merge(e,d),f); } void print(int o) { if(!o) { return; } down(o); print(tree[o].ch[0]); printf("%d ",tree[o].val); print(tree[o].ch[1]); } }; fhq_treap ft; int n,m; int main() { srand((unsigned)time(0)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { root=ft.merge(root,ft.new_node(i)); } for(int i=1;i<=m;i++) { string opx; cin>>opx; if(opx=="CUT") { int x,y,z; scanf("%d%d%d",&x,&y,&z); ft.cut(x,y,z); } else { int x,y; scanf("%d%d",&x,&y); ft.res(x,y); } } ft.print(root); return 0; }