• 【Luogu】P3391文艺平衡树(Splay)


      题目链接

      ddosvoid和自为风月马前卒教了我这道题

      他们好强啊

      如果我们要反转区间[l,r]

      我们首先把l的前驱旋转到根节点

      再把r的后继旋转到根节点的右儿子

      那么此时根节点的右儿子的左儿子所代表的就是区间l,r

      具体为啥不知道

      然后可以给splay的节点打标记,就像线段树一样

    inline void pushdown(int x){
        if(!tree[x].tag)    return;
        swap(tree[x].e[0],tree[x].e[1]);
        tree[tree[x].e[0]].tag^=1;
        tree[tree[x].e[1]].tag^=1;
        tree[x].tag=0;
    }

      这就是标记下传

      

    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    using std::swap;
    
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int root;int n;int m;
    
    struct Splay{
        struct node{
            int e[2],size,fa;
            bool tag;
        }tree[200000];
        inline int iden(int x){    return x==tree[tree[x].fa].e[1];    }
        inline void update(int x){    tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+1;    }
        inline void connect(int x,int fa,int how){    tree[x].fa=fa;    tree[fa].e[how]=x;    }
        void rotate(int x){
            int y=tree[x].fa;    if(y==root)    root=x;
            int r=tree[y].fa;
            //pushdown(r);    pushdown(y);    pushdown(x);
            int sony=iden(x);    int sonr=iden(y);
            int b=tree[x].e[sony^1];
            connect(b,y,sony);
            connect(y,x,sony^1);
            connect(x,r,sonr);
            update(y);    update(x);
        }
        inline void pushdown(int x){
            if(!tree[x].tag)    return;
            swap(tree[x].e[0],tree[x].e[1]);
            tree[tree[x].e[0]].tag^=1;
            tree[tree[x].e[1]].tag^=1;
            tree[x].tag=0;
        }
        void splay(int pos,int to){
            while(tree[pos].fa!=to){
                if(tree[tree[pos].fa].fa==to)    rotate(pos);
                else
                    if(iden(pos)==iden(tree[pos].fa)){    rotate(tree[pos].fa);    rotate(pos);    }
                    else    {    rotate(pos);    rotate(pos);    }
            }
            update(pos);
        }
        int build(int l,int r){
            if(l>r)    return 0;
            int mid=(l+r)>>1;
            int lson=build(l,mid-1);
            connect(lson,mid,0);
            int rson=build(mid+1,r);
            connect(rson,mid,1);
            tree[mid].tag=0;
            update(mid);
            return mid;
        }
        int find(int val){
            int now=root;val--;
            pushdown(now);
            while(val!=tree[tree[now].e[0]].size){
                if(tree[tree[now].e[0]].size<val){
                    val-=tree[tree[now].e[0]].size+1;
                    now=tree[now].e[1];
                }
                else    now=tree[now].e[0];
                pushdown(now);
            }
            return now;
        }
        void print(int now){
            if(!now)    return;
            pushdown(now);
            print(tree[now].e[0]);
            if(now!=1&&now!=n+2)    printf("%d ",now-1);
            print(tree[now].e[1]);
        }
    }s;
    
    
    int main(){
        n=read();    m=read();    root=s.build(1,n+2);
        while(m--){
            int l=read(),r=read();
            int x=s.find(l);    s.splay(x,0);
            int y=s.find(r+2);    s.splay(y,root);
            s.tree[s.tree[y].e[0]].tag^=1;
        }
        s.print(root);
        return 0;
    }
  • 相关阅读:
    2018年第九届蓝桥杯【C++省赛B组】第二题 明码
    2018年第九届蓝桥杯【C++省赛B组】第三题 乘积尾零
    2018年第九届蓝桥杯【C++省赛B组】第四题 测试次数
    L2-023 图着色问题
    L2-011 玩转二叉树
    获取当前的时间,转化为char[]格式unix时间戳
    创建子进程
    strerror
    gdb
    gcc
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/7940467.html
Copyright © 2020-2023  润新知