• Luogu P3391 文艺平衡树(Splay or FHQ Treap)


    这道题要求区间反转。。。好东西。。

    对于Splay:把l-1旋到根,把r+1旋到根的右儿子,这样r+1的左儿子就是整个区间了,然后对这个区间打个tg

    注意要插-Inf和Inf到树里面,防止越界,坐标要+1

    #include<cstdio>
    #include<iostream>
    #define R register int
    using namespace std;
    const int N=100010,Inf=0x3f3f3f3f;
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    int n,m,tot,rt;
    struct node{
        int fa,ch[2],sz,tg,vl;
        #define fa(x) t[x].fa
        #define ch(x,i) t[x].ch[i]
        #define sz(x) t[x].sz
        #define tg(x) t[x].tg
        #define vl(x) t[x].vl
        #define ls ch(x,0)
        #define rs ch(x,1)
    }t[N];
    inline void upd(int x) {sz(x)=sz(ls)+sz(rs)+1;}
    inline void spread(int x) {if(tg(x)) tg(ls)^=1,tg(rs)^=1,tg(x)=0,swap(ls,rs);}
    inline void rot(int x) {
        R y=fa(x),d=ch(y,1)==x;
        if(fa(y)) ch(fa(y),ch(fa(y),1)==y)=x;
        fa(x)=fa(y); fa(ch(y,d)=ch(x,d^1))=y;
        fa(ch(x,d^1)=y)=x; upd(y);
    }
    inline void Splay(int x,int f) {
        while(fa(x)!=f) {
            R y=fa(x); if(fa(y)!=f) 
                rot((ch(y,1)==x)==(ch(fa(y),1)==y)?y:x);
            rot(x);
        } upd(x); if(!f) rt=x;
    }
    inline int build(int f,int l,int r) {
        if(l>r) return 0; R md=l+r>>1,x=++tot;
        fa(x)=f,++sz(x),vl(x)=md-1;
        ls=build(x,l,md-1);rs=build(x,md+1,r);
        upd(x); return x;
    }
    inline int get(int pos) { R x=rt;
        while(1) {spread(x); R s=sz(ls); 
            if(pos==s+1) return x;
            if(pos<=s) x=ls;
            else x=rs,pos-=(s+1);
        }
    }
    inline void reverse(int l,int r) {
        l=get(l),r=get(r+2); 
        Splay(l,0),Splay(r,l); tg(ch(r,0))^=1;
    } int s; 
    inline void print(int x) { spread(x);
        if(!x) return ; print(ls); 
        if(vl(x)>=1&&vl(x)<=n) printf("%d ",vl(x)); print(rs);
    } 
    signed main() {
        n=g(),m=g(); rt=build(0,1,n+2);
        for(R i=1;i<=m;++i) {R l=g(),r=g(); reverse(l,r);}
        print(rt); putchar('
    ');
    }

    对于FHQ Treap,先把[1,l-1]和[l,n]split出来,再把[l,r]和[r+1,n]split出来,在代表区间的子树的根节点打tg,注意这道题的的split是按rank的

    不过split完忘了upd。。。我真实沙雕qwq。。。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #define R register int
    #define ls(x) ch[x][0]
    #define rs(x) ch[x][1]
    using namespace std;
    const int N=100010;
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    int n,m,tot,rt;
    int ch[N][2],sz[N],vl[N],dat[N];
    bool tg[N];
    inline void upd(int x) {sz[x]=sz[ls(x)]+sz[rs(x)]+1;}
    inline int cre(int v) {R x=++tot; vl[x]=v,sz[x]=1,dat[x]=rand(); upd(x); return x;}
    inline void spread(int x) {if(tg[x]) swap(ls(x),rs(x)),tg[ls(x)]^=1,tg[rs(x)]^=1,tg[x]=0;}
    inline void split(int o,int rk,int& x,int& y) {
        if(!o) {x=y=0; return ;} spread(o);
        if(sz[ls(o)]<rk) {x=o; split(rs(o),rk-sz[ls(o)]-1,rs(o),y); upd(x);}
        else {y=o; split(ls(o),rk,x,ls(o)); upd(y);}
    }
    inline int merge(int x,int y) {
        if(!x||!y) return x+y;
        if(dat[x]<dat[y]) {spread(x); rs(x)=merge(rs(x),y); upd(x); return x;}
        else {spread(y); ls(y)=merge(x,ls(y)); upd(y); return y;}
    }
    inline void print(int x) {if(!x) return ; spread(x); print(ls(x)); printf("%d ",vl[x]); print(rs(x));}
    signed main() { srand(100023323);
        n=g(),m=g(); for(R i=1;i<=n;++i) rt=merge(rt,cre(i)); R x=0,y=0,z=0;
        for(R i=1;i<=m;++i) { R l=g(),r=g();
            split(rt,l-1,x,y); split(y,r-l+1,y,z); tg[y]^=1; rt=merge(x,merge(y,z));
        } print(rt); while(1);
    }

    2019.05.06

  • 相关阅读:
    关于CSS网页布局id与class命名的问题
    JavaScript弹出层技术探讨文章收藏
    Jquery实现弹窗
    Asp.net中时间格式化的几种方法
    新建商品时,导入商品,随机文件名称的形成
    Linux问题:Crontab 执行shell脚本时相对路径的问题,不能识别。
    linux环境php扩展pdo_mysq安装l错误
    测试php代码的运行时间
    Apache的工作方式
    PHP时间处理
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10818879.html
Copyright © 2020-2023  润新知