Hdu-3487 Splay树,删除,添加,Lazy延迟标记操作
2015-09-21 16:28
501 查看
HDU_3487
题意:给出n和q,n代表1-n的序列,接下来q有两种操作,Cut a b c:表示把区间[a,b]截掉然后放在第c个数的后面,Flip a b 表示把区间[a,b]反转,经过一系列的q操作,最后输出操作后的序列:分析:首先建立初始化的树结构之前,先给n设置个极限范围0和n+1,防止特殊情况下越界,如果反转[a,b],则先把第a-1个数放在根节点,把b+1结点的数放在根节点的右儿子下面,此时根节点的右儿子的左儿子为根的子树就是[a,b]区间,然后把反转标记传递给该子树的根节点,如果剪切区间[a,b]则把第c+1个数旋转到根节点处,然后把根节点的右儿子为子树的最左面的节点旋转到该子树的根,此时把剪掉的子树的根节点连到根节点的右儿子的左儿子上面即可,需要注意的是,push_down和push_up的操作
codes:指针
#include"stdio.h" #include"iostream" #include"queue" #include"string.h" #define M 3000005 using namespace std; struct Text { int son[M][2],fa[M],flip[M],num[M]; int top; int root; vector<int>p; void init(int n) { top=n+2; for(int i=0;i<=n+2;i++) { num[i]=1; flip[i]=0; son[i][0]=son[i][1]=-1; fa[i]=-1; } } void Rotate(int x,int k) { int y=fa[x]; if(k==0) { son[y][1]=son[x][0]; if(son[y][1]!=-1) fa[son[y][1]]=y; push_up(y); if(son[fa[y]][0]==y) son[fa[y]][0]=x; else son[fa[y]][1]=x; fa[x]=fa[y]; son[x][0]=y; fa[y]=x; } else { son[y][0]=son[x][1]; if(son[y][0]!=-1) fa[son[y][0]]=y; push_up(y); if(son[fa[y]][0]==y) son[fa[y]][0]=x; else son[fa[y]][1]=x; fa[x]=fa[y]; son[x][1]=y; fa[y]=x; } } int Find(int k) { k++; int x=root; while(1) { push_down(x); int temp=getNum(son[x][0])+1; if(temp==k)break; else if(k<temp) x=son[x][0]; else { k-=temp; x=son[x][1]; } } return x; } void splay(int x,int f) { if(x==-1)return; while(fa[x]!=f) { int y=fa[x]; int z=fa[y]; if(z==f) { if(son[y][0]==x) Rotate(x,1); else Rotate(x,0); } else { if(son[z][0]==y) { if(son[y][0]==x) { Rotate(y,1); Rotate(x,1); } else { Rotate(x,0); Rotate(x,1); } } else { if(son[y][1]==x) { Rotate(y,0); Rotate(x,0); } else { Rotate(x,1); Rotate(x,0); } } } } if(f==top) root=x; } void RotateTo(int x,int f,int type) { if(!type) x=Find(x); splay(x,f); push_up(x); } void Reversal(int x) { if(x==-1)return; int y=son[x][0]; son[x][0]=son[x][1]; son[x][1]=y; } void creat(int l,int r,int k,int f) { if(l>r)return; int mid=(l+r)/2; if(f==top) root=mid; son[f][k]=mid; fa[mid]=f; creat(l,mid-1,0,mid); creat(mid+1,r,1,mid); push_up(mid); } int getNum(int x) { if(x==-1)return 0; return num[x]; } void push_up(int rt) { num[rt]=getNum(son[rt][0])+getNum(son[rt][1])+1; } void push_down(int rt) { if(rt==-1)return; if(flip[rt]) { flip[rt]^=1; Reversal(rt); if(son[rt][0]!=-1) flip[son[rt][0]]^=1; if(son[rt][1]!=-1) flip[son[rt][1]]^=1; } } int findLeft(int rt) { int x=rt; while(1) { push_down(x); if(son[x][0]==-1)break; x=son[x][0]; } return x; } void CUT(int a,int b,int c) { RotateTo(a-1,top,0); RotateTo(b+1,root,0); int rt=son[son[root][1]][0]; son[son[root][1]][0]=-1; RotateTo(c,top,0); int x=findLeft(son[root][1]); RotateTo(x,root,1); son[son[root][1]][0]=rt; fa[rt]=son[root][1]; } void FLIP(int a,int b) { RotateTo(a-1,top,0); RotateTo(b+1,root,0); int x=son[son[root][1]][0]; flip[x]^=1; } void dfs(int rt,int n) { if(rt==-1)return; push_down(rt); dfs(son[rt][0],n); if(rt>=1&&rt<=n) p.push_back(rt); dfs(son[rt][1],n); } void Output(int n) { dfs(root,n); printf("%d",p[0]); for(int i=1;i<(int)p.size();i++) printf(" %d",p[i]); puts(""); p.clear(); } }text; int main() { int n,q; while(scanf("%d%d",&n,&q)!=-1) { if(n==q&&n==-1)break; text.init(n); text.creat(0,n+1,0,text.top); int a,b,c; char op[10]; while(q--) { scanf("%s%d%d",op,&a,&b); if(op[0]=='C') { scanf("%d",&c); text.CUT(a,b,c); } else text.FLIP(a,b); } text.Output(n); } return 0; } /* 10 5 Cut 2 6 3 Flip 4 9 Flip 5 8 Cut 6 7 3 Flip 4 5 10 5 Flip 4 9 Flip 5 8 Cut 6 7 3 Flip 4 5 10 1 Flip 2 9 */
View Code
相关文章推荐
- 第四周-项目4-建立双链表算法库
- 第3周实践项目2--建设“顺序表”算法库
- C++ using namespace std 详解
- 沙盒机制--SandBox
- 信鸽推送
- httpResponse的getEntity为空,获取了这个数据在解析的时候出现了String不能转换成json对象
- 【VBS教程2】:(全网首发)怎么用sendkeys传送中文字符
- 小偷分赃 等比求和 CodeChef Bank robbery
- [LintCode]找峰值 II
- Java中的队列:java.util.Queue接口
- XE8-indy10中TIdTCPClient控件Disconnect源码分析
- Android 开发环境下载地址 -- 百度网盘 adt-bundle android-studio sdk adt 下载
- openfire插件开发之完美开发
- cxf发布和调用webservice
- 本土化手机游戏需要考虑的10种语言
- Java解析Json对象
- Docker数据管理
- 图的深度优先搜索和广度优先搜索
- hdu 5464 Clarke and problem dp
- bootstrap 学习