HDOJ 3487 Play with Chain【splay】
2014-02-13 12:59
281 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3487
题意:给定一串序列,有两种操作:①把某段区间切到某一点后面②把某个区间颠倒
分析:这题由于涉及到区间移动,所以需要用到平衡树的旋转操作。于是新学了个splay(有个演示网站:http://www.cs.usfca.edu/~galles/visualization/SplayTree.html),学了半天还是没搞懂splay为何是平衡树。。
代码:
题意:给定一串序列,有两种操作:①把某段区间切到某一点后面②把某个区间颠倒
分析:这题由于涉及到区间移动,所以需要用到平衡树的旋转操作。于是新学了个splay(有个演示网站:http://www.cs.usfca.edu/~galles/visualization/SplayTree.html),学了半天还是没搞懂splay为何是平衡树。。
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> #include<cmath> #define N 300050 using namespace std; struct node { node *ch[2],*p; int val,sz,rev; void init(int _v){ch[0]=ch[1]=p=NULL;val=_v;rev=0;sz=1;}; bool d(){return p->ch[1]==this;} void setch(int d,node *nc){ch[d]=nc;if(nc)nc->p=this;} void updata() { sz = 1; if(ch[0]) sz += ch[0]->sz; if(ch[1]) sz += ch[1]->sz; } void pushdown() { if(rev) { swap(ch[0], ch[1]); rev = 0; if(ch[0]) ch[0]->rev ^= 1; if(ch[1]) ch[1]->rev ^= 1; } } }tree ,*root,*cur; int num,n,m; node* maken(int v) { cur->init(v); return cur++; } node* build(int l,int r) { if(l > r) return NULL; int m = (l + r) >> 1; node *x = maken(m); x->setch(0, build(l, m-1)); x->setch(1, build(m+1, r)); x->updata(); return x; } void show(node *u){ u->pushdown(); if(u->ch[0])show(u->ch[0]); if(num>0&&num<=n){ printf("%d",u->val); printf("%c",num==n?'\n':' '); } num++; if(u->ch[1])show(u->ch[1]); } node* select(int k)//找到点权为v的点 { node *x=root; while(true) { x->pushdown(); int tmp = x->ch[0]?x->ch[0]->sz:0; if(k == tmp) break; if(k < tmp) x = x->ch[0]; else x = x->ch[1], k-=tmp+1; } return x; } void rot(node *x) { node *y=x->p, *z=y->p; y->pushdown();x->pushdown(); int d=x->d(); if(z) z->setch(y->d(), x); y->setch(d, x->ch[!d]); x->setch(!d, y); y->updata(); if(!z) root=x, x->p=NULL; } void splay(node *st,node *en) { while(st->p!=en)rot(st);st->updata(); } void print() { for(int i=0;i<=n+1;i++) { cout<<tree[i].val<<' '; if(tree[i].ch[0])cout<<tree[i].ch[0]->val<<' '; if(tree[i].ch[1])cout<<tree[i].ch[1]->val; cout<<endl; } } int main() { while(scanf("%d%d",&n,&m)&&(n>=0||m>=0)) { cur=tree;root=build(0,n+1); char cmd[5]; while(m--) { int l,r;scanf("%s%d%d",cmd,&l,&r); node *ln=select(l-1),*rn=select(r+1); splay(ln,NULL);splay(rn,ln); node *bn=rn->ch[0]; if(cmd[0]=='C'){ int pos;scanf("%d",&pos); rn->setch(0,NULL);rn->updata();ln->updata();//把目标区间截出来 node *lpn=select(pos),*rpn=select(pos+1); splay(lpn,NULL);splay(rpn,lpn); rpn->setch(0,bn);rpn->updata();lpn->updata();//把目标区间所在的子树接上 } else if(bn)bn->rev^=1; }num=0;show(root); // print(); } return 0; }
相关文章推荐
- hdu 3487 Play with Chain(splay)
- Splay 模板题 一 hdu 3487 play with chain
- 【HDU】3487 Play with Chain 【splay】
- HDU 3487 Play with Chain | Splay
- hdu 3487 Play with Chain (Splay树) 区间切割 插入 翻转
- Play with Chain HDU - 3487 splay区间翻转,区间位移
- HDU 3487 Play with Chain 伸展树splay
- hdu 3487 Play with Chain splay tree
- HDU 3487 Play with Chain [平衡树splay]
- HDU 3487 Play with Chain (Splay)
- HDU 3487 Play with Chain(Splay 经典操作)
- hdu 3487 Play with Chain splay tree
- 【HDOJ】3487 Play with Chain
- 【HDU】3487 Play with Chain Splay
- HDOJ 3487 Play with Chain
- HDU 3487(Play with Chain-Splay)[template:Splay]
- hdoj(hdu)-3487-play with the chain-SplayTree
- HDU 3487 Play with Chain(Splay)
- hdu 3487 Play with Chain(splay区间剪切,翻转)
- Splay树(区间添加删除 | 区间翻转)——HDU 3487 Play with Chain