• [洛谷P3391]【模板】文艺平衡树(Splay)


    题目描述:https://www.luogu.org/problemnew/show/P3391

    解析:在这里主要讲一下对splay上点的权值的看法。首先,我们发现一颗splay的中序遍历始终是不变的,所以想到用splay的中序遍历来表示原数组的位置。那么怎么实现呢?我们只需要刚开始建树的时候以位置为权值来建树。换一种说法,以位置建树只是为了让splay的中序遍历有序。所以事实上,这颗splay任然是以原数组的数为权值的,只不过是刚开始建树的时候换了一个建树方式。那么有同学可能会问,swap过后不就不满足splay左小右大的性质了吗?肯定不满足啊。有同学可能会问另外一个问题,怎么保证r+1一定能旋转到l-1的右儿子去呢,不是已经不满足splay的性质了吗?注意,splay的旋转操作是跟点的权值没有关系的,它只是跟splay怎么建的树有关系。

        附上代码(origin为原数组):

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int MAXN=100005;
    int n,m;
    int root;
    struct Node{
        int size,son[2],val,fa,tag;
    }node[MAXN];
    int ndnum=0;
    int origin[MAXN];
    
    int check(int x){
        return x==node[node[x].fa].son[1];
    }
    
    void update(int x){
        node[x].size=node[node[x].son[0]].size+node[node[x].son[1]].size+1;
    }
    
    void rotate(int x){
        int y=node[x].fa,z=node[y].fa,d=check(x),xx=node[x].son[d^1];
        node[y].son[d]=xx;node[xx].fa=y;
        node[z].son[check(y)]=x;node[x].fa=z;
        node[x].son[d^1]=y;node[y].fa=x;
        update(y);update(x);
    } 
    
    void splay(int x,int to=0){
        while(node[x].fa!=to){
            int y=node[x].fa,z=node[y].fa;
            if(z!=to){
                if(check(x)==check(y)) rotate(y);
                else rotate(x);
            }    
            rotate(x);
        }
        if(!to) root=x;
    }
    
    void insert(int x){
        int cur=root,f=0;
        while(cur&&node[cur].val!=x){
            f=cur;
            cur=node[cur].son[x>node[cur].val];
        }
        cur=++ndnum;
        if(f) node[f].son[x>node[f].val]=cur;
        node[cur].size=1;node[cur].tag=0;
        node[cur].son[0]=node[cur].son[1]=0;
        node[cur].val=x;node[cur].fa=f;
        splay(cur);
    }
    
    void pushdown(int cur){
        if(node[cur].tag){
            node[node[cur].son[0]].tag^=1;
            node[node[cur].son[1]].tag^=1;
            node[cur].tag=0;
            swap(node[cur].son[0],node[cur].son[1]);
        }
    }
    
    int kth(int k){
        int cur=root;
        while(1){
            pushdown(cur);
            if(k<=node[node[cur].son[0]].size)
            cur=node[cur].son[0];
            else{
                k-=node[node[cur].son[0]].size+1;
                if(!k) return cur;
                cur=node[cur].son[1];
            } 
        }
    } 
    
    void reserve(int l,int r){
        l=kth(l-1);r=kth(r+1);
        splay(l);splay(r,l);
        node[node[node[root].son[1]].son[0]].tag^=1;
    }
    
    void write(int cur){
        pushdown(cur);
        if(node[cur].son[0]) write(node[cur].son[0]);
        if(node[cur].val>1&&node[cur].val<n+2) printf("%d ",origin[node[cur].val-1]);
        if(node[cur].son[1]) write(node[cur].son[1]);
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&origin[i]); 
        for(int i=1;i<=n+2;i++) insert(i);
        for(int i=1;i<=m;i++){
            int l,r;
            scanf("%d%d",&l,&r);
            reserve(l+1,r+1);
        }
        write(root);
        return 0;
    }
    View Code
  • 相关阅读:
    2017-2018-1 团队名称 第一周 作业
    20162307 2017-2018-1 《程序设计与数据结构》第3周学习总结
    20162307 2017-2018-1 《程序设计与数据结构》第1周学习总结
    20161207 结对编程-马尔可夫链-自动生成短文
    20162307 2016-2017-2《程序设计与数据结构》课程总结
    20162307 实验五 网络编程与安全
    20162307 结对编程-四则运算(挑战出题)
    20162306 2016-2017-2《程序设计与数据结构》课程总结
    实验五 网络编程与安全实验报告 20162306陈是奇
    实验补充
  • 原文地址:https://www.cnblogs.com/JoshDun/p/11183043.html
Copyright © 2020-2023  润新知