数据结构入门6—文艺平衡树(Splay)
来源:互联网 发布:matlab矩阵乘法代码 编辑:程序博客网 时间:2024/06/04 19:05
早就听说 Splay 就是不管干什么都Splay一下就可以了,但是听说傻可开脑洞打代码打了250行,惊恐。
于是先学treap结果没想到一调试就搞了三个月。但是其实写过treap再学Splay就相对容易一些了。
那就先学只有区间翻转的文艺平衡树。
一开始一直弄不懂它的翻转操作,感觉很迷。但是其实和treap很像,只不过是以翻两下为一组,然后每次Splay把节点旋到指定位置。在三点一线的时候,先旋转x的父亲,再旋转x,除此之外都直接旋转x就好了。
除此之外还要注意一些细节问题。一个是关于添加虚节点的问题。比如我们要翻转[l,r]这个区间,我们可以把r+1这个点Splay到跟,然后把l-1这个点Splay到跟的左儿子,然后直接把l-1的右儿子打上标记。但是如果l==1或r==n,那样就必须添加一个能表示l-1(0)的节点和一个能表示r+1(n+1)的节点。
Splay有两种写法,白书上是没有父亲指针的,但是有父亲指针的适用性更强。
模板题
//Serene#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>using namespace std;const int maxn=1e5+10;int n,m,root;int aa;char cc;int read() {aa=0;cc=getchar();while(cc<'0'||cc>'9') cc=getchar();while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();return aa;}struct Node{int son[2],laz,fa,sum;}node[maxn];void bld(int pos,int l,int r) {if(!pos||l>r) return ;if(l==r) {node[pos].sum=1;return;}if(pos!=l) node[pos].son[0]=(pos+l)>>1;if(pos!=r) node[pos].son[1]=(pos+2+r)>>1;node[node[pos].son[0]].fa=node[node[pos].son[1]].fa=pos;bld(node[pos].son[0],l,pos-1); bld(node[pos].son[1],pos+1,r);node[pos].sum+=node[node[pos].son[0]].sum+node[node[pos].son[1]].sum+1;}void ud(int pos) {if(!node[pos].laz||node[pos].sum==1) {node[pos].laz=0;return ;//}swap(node[pos].son[0],node[pos].son[1]);if(node[pos].son[0]) node[node[pos].son[0]].laz^=1;if(node[pos].son[1]) node[node[pos].son[1]].laz^=1;node[pos].laz=0;}int find(int pos,int x) {ud(pos);if(node[node[pos].son[0]].sum+1==x) return pos;if(x<=node[node[pos].son[0]].sum) return find(node[pos].son[0],x);return find(node[pos].son[1],x-(node[node[pos].son[0]].sum+1));}void rotate(int pos,int &to) {int x=node[pos].fa,y=node[x].fa;int p1=node[x].son[1]==pos,p2=node[y].son[1]==x;node[x].son[p1]=node[pos].son[!p1];node[node[pos].son[!p1]].fa=x;// node[pos].son[!p1]=x;node[pos].sum=node[x].sum;node[x].sum=node[node[x].son[0]].sum+node[node[x].son[1]].sum+1;node[pos].fa=y;node[x].fa=pos;if(root==x) root=pos;else {node[y].son[p2]=pos;if(x==to) to=pos;}}void splay(int pos,int &to) {ud(pos);int x,y,p1,p2;while(to!=pos) {x=node[pos].fa;y=node[x].fa;if(y) ud(y);ud(x);ud(pos);if(x!=to) {if(node[x].son[1]==pos ^ node[y].son[1]==x) rotate(pos,to);else rotate(x,to);}rotate(pos,to);}}void fz(int l,int r) {if(l==r) return ;int x=find(root,l),y=find(root,r+2);splay(y,root); splay(x,node[root].son[0]);node[node[x].son[1]].laz^=1;}void dfs(int pos) {ud(pos);if(node[pos].son[0]) dfs(node[pos].son[0]);if(pos>1&&pos<n+2) printf("%d ",pos-1);if(node[pos].son[1]) dfs(node[pos].son[1]);}int main() {n=read();m=read();root=(n+3)>>1;bld(root,1,n+2);int l,r;for(int i=1;i<=m;++i) {l=read();r=read();fz(l,r);}dfs(root);return 0;}
阅读全文
0 0
- 数据结构入门6—文艺平衡树(Splay)
- 数据结构--文艺平衡树(Splay)
- BZOJ 3223 文艺平衡树 (splay)
- BZOJ3223 文艺平衡树(Splay)
- 文艺平衡树(splay旋转操作)
- 【模板】文艺平衡树(Splay)
- P3391 【模板】文艺平衡树(Splay)
- [BZOJ3223] 文艺平衡树 - splay
- [BZOJ3223]文艺平衡树 splay
- bzoj3223文艺平衡树splay
- [BZOJ3223]文艺平衡树(平衡树splay)
- [BZOJ3223]文艺平衡树(平衡树splay)
- 【splay】splay小结 文艺平衡树
- BZOJ3223&3224 文艺&普通平衡树 Splay模板(数组)
- [BZOJ 3223]Tyvj 1729 文艺平衡树(Splay)
- BZOJ3323 文艺平衡树 (splay 绿色无毒模板)
- 区间翻转 bzoj 3223 文艺平衡树 (splay)
- luogu #3391 【模板】文艺平衡树(splay)
- POJ3320-Jessica's Reading Problem
- HDU 6103 Kirinriki
- jvm 类加载机制
- RedHat 6.2 Linux修改yum源免费使用CentOS源
- tf.subtract()
- 数据结构入门6—文艺平衡树(Splay)
- 1109. Group Photo (25)
- Java深入浅出——Java基础(1)
- 数据挖掘十大经典算法
- 单点登录原理与简单实现
- UIScrollView使用自动布局设置以及contentSize滚动问题
- ajax 提交及表单提交报错
- I
- SVN学习小记