[模板] 文艺平衡树
由于中序遍历不会因为旋转改变,平衡树可以作为区间树使用。
翻转用打标记的方法,splay(x,y)代表把x接到以y为根的子树下面。
#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=100005;
int n,m;
int val[MAXN],siz[MAXN],mk[MAXN];
int ch[MAXN][2],fa[MAXN];
int root,tot;
inline int newnode(int x){val[++tot]=x;siz[tot]=1;return tot;}
inline bool check(int x){return x==ch[fa[x]][1];}
inline void pushup(int x){siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;}
inline void pushdown(int x){if(!mk[x]) return;mk[ch[x][0]]^=1;mk[ch[x][1]]^=1;mk[x]^=1;swap(ch[x][0],ch[x][1]);}
void rotate(int x){
int y=fa[x],z=fa[fa[x]];
pushdown(y);pushdown(x);
bool ck=check(x);
fa[ch[x][ck^1]]=y;
ch[y][ck]=ch[x][ck^1];
ch[x][ck^1]=y;fa[y]=x;fa[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
pushup(y);pushup(x);
}
void splay(int x,int y){
for(int f=fa[x];f!=y;rotate(x),f=fa[x])
if(fa[f]!=y) rotate(check(x)==check(f)?f:x);
if(!y) root=x;
}
void insert(int x){
if(!root){root=newnode(x);return;}
int cur=root,f=0;
while(1){
if(val[cur]==x){splay(x,0);return;}
f=cur;cur=ch[cur][x>val[cur]];
if(!cur){cur=newnode(x);fa[cur]=f;ch[f][x>val[f]]=cur;pushup(f);splay(cur,0);return;}
}
}
int kth(int x){
int cur=root;
while(1){
pushdown(cur);
if(x<=siz[ch[cur][0]]) cur=ch[cur][0];
else{
x-=siz[ch[cur][0]]+1;
if(x<=0) return val[cur];
cur=ch[cur][1];
}
}
}
void rev(int x,int y){
x=kth(x);y=kth(y+2);
splay(x,0);splay(y,x);
mk[ch[ch[root][1]][0]]^=1;
}
void print(int cur){
if(!cur) return;
pushdown(cur);
print(ch[cur][0]);
if(cur>1&&cur<n+2) printf("%d ",val[cur]-1);
print(ch[cur][1]);
}
int main(){
cin>>n>>m;
int x,y;
for(int i=1;i<=n+2;i++) insert(i);
for(int i=1;i<=m;i++){
cin>>x>>y;
rev(x,y);
}
print(root);
return 0;
}
建树可以构造一棵非常平衡的二叉树
#include<iostream>
#include<cstdio>
using namespace std;
const int INF=1<<30;
const int MAXN=100005;
int n,m;
int val[MAXN],siz[MAXN],mk[MAXN];
int ch[MAXN][2],fa[MAXN];
int root,tot;
inline int newnode(int x) {
val[++tot]=x;
siz[tot]=1;
return tot;
}
inline bool check(int x) {
return x==ch[fa[x]][1];
}
inline void pushup(int x) {
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
inline void pushdown(int x) {
if(mk[x]&&x) {
mk[ch[x][0]]^=1;
mk[ch[x][1]]^=1;
mk[x]^=1;
swap(ch[x][0],ch[x][1]);
}
}
void rotate(int x) {
int y=fa[x],z=fa[fa[x]];
pushdown(y);
pushdown(x);
bool ck=check(x);
fa[ch[x][ck^1]]=y;
ch[y][ck]=ch[x][ck^1];
ch[x][ck^1]=y;
fa[y]=x;
fa[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
pushup(y);
pushup(x);
}
void splay(int x,int y) {
for(int f=fa[x]; f!=y; rotate(x),f=fa[x])
if(fa[f]!=y) rotate(check(x)==check(f)?f:x);
if(!y) root=x;
}
bool insert(int x) {
if(!root) return root=newnode(x),1;
int cur=root,f=0;
while(1) {
if(val[cur]==x) return splay(cur,0),0;
f=cur;
cur=ch[cur][x>val[cur]];
if(!cur) {
cur=newnode(x);
fa[cur]=f;
ch[f][x>val[f]]=cur;
pushup(f);
splay(cur,0);
return 1;
}
}
}
int kth(int x) {
int cur=root;
while(1) {
pushdown(cur);
if(x<=siz[ch[cur][0]]) cur=ch[cur][0];
else {
x-=siz[ch[cur][0]]+1;
if(x<=0) return cur;
cur=ch[cur][1];
}
}
}
void rev(int x,int y) {
x=kth(x);
y=kth(y+2);
splay(x,0);
splay(y,x);
mk[ch[ch[root][1]][0]]^=1;
}
void print(int cur) {
if(!cur) return;
pushdown(cur);
print(ch[cur][0]);
int v=val[cur];
if(v!=INF&&v!=-INF) printf("%d ",v);
print(ch[cur][1]);
}
int a[MAXN];
int build(int pre,int l,int r){
int mid=(l+r)>>1;
int cur=newnode(a[mid]);
fa[cur]=pre;
l<mid?ch[cur][0]=build(cur,l,mid-1):0;
r>mid?ch[cur][1]=build(cur,mid+1,r):0;
pushup(cur);
return cur;
}
int main() {
cin>>n>>m;
int x,y;
for(int i=2; i<=n+1; i++) a[i]=i-1;
a[1]=-INF;a[n+2]=INF;
root=build(0,1,n+2);
while(m--) {
cin>>x>>y;
rev(x,y);
}
print(root);
return 0;
}
本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247384.html