数据结构入门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;}


原创粉丝点击