bzoj3223: Tyvj 1729 文艺平衡树(伸展树)
来源:互联网 发布:cmf和cms 编辑:程序博客网 时间:2024/05/29 17:04
题目传送门
这道题让我觉得我可以认真写下博客了。
解法:
按照位置来建立伸展树,本身的值则是这个位置上是什么值。
即:
左子树在序列中位置都比我前。
右子树在序列中位置都比我后。
最后得出来的树我们按照中序遍历输出每个点的权值就好。
怎么反转?
既然左子树比我前右子树比我后那么反转的话我只要把家族所有人对调一下就行了嘛。
也就是整棵子树的左右孩子都对调。
那么问题就是怎么把同一段序列放到同一棵子树里。
假设翻转区间l,r
那么我们把l-1这个位置的点旋转到根节点。
那么l-1的右子树就都是在l-1后面的当然也包括l~r。
然后把r+1这个位置的点旋转到根节点的儿子也就是l-1的儿子。
那么r+1的左子树就都是在r+1前面的了。
那么既然在l-1后面,在r+1前面也就是l到r啦。
所以把这棵子树翻转一下就行啦。
当然不能每次都翻转,所以打懒标记咯。
代码实现:
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct node { int n,c,d,f,son[2],fz; //fz即为翻转标记}tr[110000];int len;void update(int x) { int lc=tr[x].son[0],rc=tr[x].son[1]; tr[x].c=tr[lc].c+tr[rc].c+1;}void re(int x) { int lc=tr[x].son[0],rc=tr[x].son[1]; tr[lc].fz^=1;tr[rc].fz^=1;tr[x].fz=0; swap(tr[x].son[0],tr[x].son[1]);}void add(int d,int f) { len++; tr[len].d=d;tr[len].f=f;tr[len].n=tr[len].c=1; if(d<tr[f].d) tr[f].son[0]=len; else tr[f].son[1]=len; tr[len].son[0]=tr[len].son[1]=0;}void rotate(int x,int w) { int f=tr[x].f,ff=tr[f].f; int r,R; r=tr[x].son[w];R=f; tr[R].son[1-w]=r; if(r!=0) tr[r].f=R; r=x;R=ff; if(tr[R].son[0]==f) tr[R].son[0]=r; else tr[R].son[1]=r; tr[r].f=R; r=f;R=x; tr[R].son[w]=r; tr[r].f=R; update(f);update(x);}int s[110000],root;void splay(int x,int rt) { int t=0,tmp=x; while(tr[tmp].f!=rt) { s[++t]=tmp;tmp=tr[tmp].f; } s[++t]=tmp; for(int i=t;i>=1;i--) if(tr[s[i]].fz==1) re(s[i]); while(tr[x].f!=rt) { int f=tr[x].f,ff=tr[f].f; if(ff==rt) { if(tr[f].son[0]==x) rotate(x,1); else rotate(x,0); } else { if(tr[f].son[0]==x&&tr[ff].son[0]==f) { rotate(f,1);rotate(x,1); } else if(tr[f].son[0]==x&&tr[ff].son[1]==f) { rotate(x,1);rotate(x,0); } else if(tr[f].son[1]==x&&tr[ff].son[0]==f) { rotate(x,0);rotate(x,1); } else if(tr[f].son[1]==x&&tr[ff].son[1]==f) { rotate(f,0);rotate(x,0); } } } if(rt==0) root=x;}int ins(int l,int r){ if(l>r) return 0; int mid=(l+r)/2; len++;int now=len; tr[now].d=mid; int lc=ins(l,mid-1),rc=ins(mid+1,r); if(lc!=0) tr[lc].f=now; if(rc!=0) tr[rc].f=now; tr[now].son[0]=lc;tr[now].son[1]=rc; tr[now].c=tr[lc].c+tr[rc].c+1; return now;}int findpaiming(int k) { int x=root; while(1) { if(tr[x].fz==1) re(x); int lc=tr[x].son[0],rc=tr[x].son[1]; if(k<=tr[lc].c) x=lc; else if(k>tr[lc].c+1) { k-=tr[lc].c+1;x=rc; } else break; } return x;}void f_z(int x,int y) { int l=findpaiming(x-1),r=findpaiming(y+1); splay(l,0);splay(r,l); //详情看上面题解 tr[tr[r].son[0]].fz^=1; splay(tr[r].son[0],0);}int ans[110000],slen;void shu(int x) { //中序遍历输出答案 if(tr[x].fz==1) re(x); if(tr[x].son[0]!=0) shu(tr[x].son[0]); ans[++slen]=tr[x].d; if(tr[x].son[1]!=0) shu(tr[x].son[1]);}int main() { int n,m;scanf("%d%d",&n,&m); root=len=0; root=ins(0,n+1); for(int i=1;i<=m;i++) { int x,y;scanf("%d%d",&x,&y); f_z(x+1,y+1); } slen=0;shu(root); for(int i=2;i<slen;i++) printf("%d ",ans[i]); return 0;}
阅读全文
0 0
- bzoj3223: Tyvj 1729 文艺平衡树(伸展树)
- [Bzoj3223]Tyvj 1729 文艺平衡树
- [BZOJ3223]Tyvj 1729 文艺平衡树
- 【bzoj3223】Tyvj 1729 文艺平衡树 Splay
- [BZOJ3223] Tyvj 1729 文艺平衡树
- bzoj3223: Tyvj 1729 文艺平衡树
- 【bzoj3223】Tyvj 1729 文艺平衡树
- bzoj3223 && Tyvj 1729 文艺平衡树
- 【BZOJ3223】Tyvj 1729 文艺平衡树【Splay】
- bzoj3223: Tyvj 1729 文艺平衡树
- BZOJ3223: Tyvj 1729 文艺平衡树
- bzoj3223 Tyvj 1729 文艺平衡树
- 【bzoj3223】Tyvj 1729 文艺平衡树
- bzoj3223 Tyvj 1729 文艺平衡树 (splay)
- BZOJ3223: Tyvj 1729 文艺平衡树(洛谷P3391)
- bzoj3223文艺平衡树 原tyvj题目
- bzoj3223: Tyvj 1729 文艺平衡树 splay裸区间旋转
- BZOJ3223——Tyvj 1729 文艺平衡树
- Android笔记
- ActiveMQ入门到精通3-ActibeMQ API详解
- 笔记————C#数据库删除
- 关于activity的管理
- 请求服务器时的状态码详解
- bzoj3223: Tyvj 1729 文艺平衡树(伸展树)
- codevs2218 补丁VS错误(状压+spfa更新)
- JMeter测试工具Timer定时器的介绍使用
- angular的查询添加排序
- WPF学习之绘图和动画
- 判断拼接url
- 图书管理系统
- 抢购是如今很常见的一个应用场景,主要需要解决的问题
- RunTimeException-Could not read input channel file descriptors from parcel