zoukankan      html  css  js  c++  java
  • [模板] 文艺平衡树

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

  • 相关阅读:
    mac下 brew 切换阿里镜像
    梨视频(PearVideo)下载解析的方法和技巧,梨视频下载到本地
    如何快速的下载Tumblr(汤不热)视频?操作步骤很简单,快来看看!
    什么是json? 什么是xml?JSON与XML的区别比较
    如何下载Twitter视频?最简单的保存推特视频的方法
    【收藏】轻松导出全民K歌里任何人录制的短视频(MV)、歌曲的方法
    【小白技术笔记】保存皮皮虾APP无水印视频到手机相册,只需要三步 [技术干货]
    技术干货!腾讯微视短视频去水印下载到本地的方法
    P1562 还是N皇后
    循环赛日程表
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9247384.html
Copyright © 2011-2022 走看看