zoukankan      html  css  js  c++  java
  • hdu1890 splay维护区间翻转

    这题的建模有点不太一样,是按结点横坐标赋予键值的

    同时每次rotate和splay时都要注意下往上往下更新

    /*
    先建立好splay tree,将结点按num/输入顺序排序,遍历时每次将当前结点提到根节点,输出其在splay树中排第几个
    然后rev左子树,最后remove
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #include<algorithm>
    #define maxn 100005
    struct A{
        int num,id;
        bool operator < (const A &a) const {
            if(num==a.num) return id<a.id;
            return num<a.num;
        }
    }a[maxn];
    int pre[maxn],ch[maxn][2],size[maxn],keys[maxn],tot,root,n;
    int rev[maxn];
    inline void pushup(int r){
        size[r]=size[ch[r][0]]+size[ch[r][1]]+1;
    }
    void update(int r){//就是交换r的两个子区间
        if(!r) return;
        else {
            swap(ch[r][0],ch[r][1]);
            rev[r]^=1;
        }       
    }      
    inline void pushdown(int r){
        if(rev[r]){//把左右子树rev
            update(ch[r][0]);
            update(ch[r][1]);
            rev[r]=0;
        }
    }
    inline void newnode(int &r,int fa,int key){
        r=key;
        pre[r]=fa;
        ch[r][0]=ch[r][1]=0;
        size[r]=0;
        keys[r]=key;
        rev[r]=0;
    }
    void build(int &r,int L,int R,int fa){
        if(L>R) return;
        int m=L+R>>1;
        newnode(r,fa,m);
        build(ch[r][0],L,m-1,r);
        build(ch[r][1],m+1,R,r);
        pushup(r);
    }
    void init(){
        root=tot=0;
        ch[root][0]=ch[root][1]=0;
        size[root]=0;
        rev[root]=0;
        build(root,1,n,0);
    }           
    //rotate操作只会改变r,fa,ch[r][kind]三个结点
    void rotate(int x,int kind){
        int fa=pre[x];
        pushdown(fa);
        pushdown(x);
        ch[fa][!kind]=ch[x][kind];
        pre[ch[x][kind]]=fa;
        if(pre[fa])
            ch[pre[fa]][ch[pre[fa]][1]==fa]=x;
        pre[x]=pre[fa];
        pre[fa]=x;
        ch[x][kind]=fa;
        pushup(fa);
        pushup(x);
    }           
    void splay(int r,int goal){
        pushdown(r);
        while(pre[r]!=goal){
            if(pre[pre[r]]==goal){
                pushdown(pre[r]);
                pushdown(r);
                rotate(r,ch[pre[r]][0]==r);
            }
            else {
                pushdown(pre[pre[r]]);
                pushdown(pre[r]);
                pushdown(r);
                int fa=pre[r];
                int kind=(ch[pre[fa]][0]==fa);
                if(ch[fa][kind]==r){//方向相反
                    rotate(r,!kind);
                    rotate(r,kind);
                }
                else {
                    rotate(fa,kind);
                    rotate(r,kind);
                }
            }
        }
        if(goal==0) root=r;
        pushup(r);
    }     
    void remove(){//删掉根节点
        if(ch[root][0]==0){
            root=ch[root][1];
            pre[root]=0;
        }
        else {
            pushdown(root);
            int tmp=ch[root][0];
            while(ch[tmp][1])
                pushdown(tmp),tmp=ch[tmp][1];
            splay(tmp,root);
            ch[tmp][1]=ch[root][1];
            pre[ch[root][1]]=tmp;
            root=tmp;
            pre[root]=0;
            pushup(root);
        }
    }
      
    
    
    
    int main(){
        while(scanf("%d",&n) && n){
            init();
                for(int i=1;i<=n;i++)
                scanf("%d",&a[i].num),a[i].id=i;
            sort(a+1,a+1+n);
            for(int i=1;i<n;i++){
                splay(a[i].id,0);//按权值大小遍历点
                update(ch[root][0]);//逆转区间
                printf("%d ",i+size[ch[root][0]]);//输出结点在当前伸展树中排的序号
                remove(); 
            }
              printf("%d
    ",n);
        }
        return 0;
    }
  • 相关阅读:
    [From 11.1~11.4]事件
    [From 10.1~10.5] 对象和集合初始化器(C#语法糖系列)
    [From 9.3]out和ref关键字
    [From 8.5]转换操作符方法
    将博客搬至CSDN
    QPS 与 TPS 简介
    在cenos中,通过subversion源码进行安装
    no acceptable C compiler found in $PATH
    tgz解压
    程序中的@Override是什么意思?
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9998223.html
Copyright © 2011-2022 走看看