[模板] 文艺平衡树

由于中序遍历不会因为旋转改变,平衡树可以作为区间树使用。
翻转用打标记的方法,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;
}

猜你喜欢

转载自blog.csdn.net/gh0stcai/article/details/80687646