非旋treap

非旋treap

基本操作

简述

\(FHQ\space treap\)借用了\(treap\)的特点,基于\(split\)\(merge\)操作实现,因其不用旋转,又叫非旋\(treap\),优点是好理解,上手快,代码短 (ps: 重点是好写)

#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]

struct tree{
    int sz,val,pri,ch[2];
}t[N<<2];

il int add(cs int val){
    t[++cnt].sz=1;
    t[cnt].val=val;
    t[cnt].pri=srd();
    return cnt;
}

il void upd(cs int rt){
    t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;
}

分裂

这里是按照权值分裂,小于等于\(k\)的在左边(\(x\)),大于的在右边(\(y\)),也可以按子树大小分

il void split(cs int rt,cs int k,int &x,int &y){
    if(!rt) x=y=0;
    else{
        if(t[rt].val<=k) x=rt,split(rs(rt),k,rs(x),y);
        else y=rt,split(ls(rt),k,x,ls(y));
        t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
    }
    return;
}

合并

要保证\(x\)的权值(或子树大小)比\(y\)的小,具体看分裂按什么分

il int merge(cs int x,cs int y){ //val[x]<val[y]
    if(!x||!y) return x+y;
    if(t[x].pri<t[y].pri){
        rs(x)=merge(rs(x),y);
        t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
        return x;
    } 
    else{
        ls(y)=merge(x,ls(y));
        t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
        return y;
    }
}

\(insert\)

to be continue~

il void ins(int &rt,cs int val){
    ri int x,y;
    split(rt,val,x,y);
    rt=merge(merge(x,add(val)),y);
    return;
}

\(delete\)

to be continue~

il void del(int &rt,cs int val){
    ri int x,y,z;
    split(rt,val,x,z),split(x,val-1,x,y);
    y=merge(ls(y),rs(y));
    rt=merge(merge(x,y),z);
    return;
}

查询\(k\)的排名

to be continue~

il int rnk(int &rt,cs int val){
    ri int x,y,as;
    split(rt,val-1,x,y);
    as=t[x].sz+1,rt=merge(x,y);
    return as;
}

查询排名为\(k\)的数

to be continue~

il int kth(cs int rt,int k){
    ri int o=rt;
    while(1){//rt=0
        if(k<=t[ls(o)].sz) o=ls(o);
        else if(k==t[ls(o)].sz+1) return o;//
        else k-=t[ls(o)].sz+1,o=rs(o);//
    }
}

查询\(k\)的前驱

to be continue~

il int pre(int &rt,cs int val){
    ri int x,y,as;
    split(rt,val-1,x,y);
    as=t[kth(x,t[x].sz)].val;
    rt=merge(x,y);
    return as;
}

查询\(k\)的后继

to be continue~

il int nxt(int &rt,cs int val){
    ri int x,y,as;
    split(rt,val,x,y);
    as=t[kth(y,1)].val;
    rt=merge(x,y);
    return as;
}
code
#include <bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define F(s) freopen(#s".in","r",stdin),freopen(#s".out","w",stdout);            
using namespace std;

namespace Q{
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=getchar();
        while(!isdigit(c)) f|=(c==45),c=getchar();
        while(isdigit(c)) x=x*10+(c^48),c=getchar();
        return f?-x:x;
    }
    il void wt(int x){
        if(x<0) x=-x,putchar(45);
        if(x>=10) wt(x/10);
        return putchar(x%10|48),void();
    }
    il void wn(int x,char c=10){
        wt(x),putchar(c);
    }
} using namespace Q;

cs int N=1e5+5;
int cnt,rot,n;
mt19937 srd(time(0));

namespace fhq_treap{
    #define ls(x) t[x].ch[0]
    #define rs(x) t[x].ch[1]

    struct tree{
        int sz,val,pri,ch[2];
    }t[N<<2];

    il int add(cs int val){
        t[++cnt].sz=1;
        t[cnt].val=val;
        t[cnt].pri=srd();
        return cnt;
    }

    il void split(cs int rt,cs int k,int &x,int &y){
        if(!rt) x=y=0;
        else{
            if(t[rt].val<=k) x=rt,split(rs(rt),k,rs(x),y);
            else y=rt,split(ls(rt),k,x,ls(y));
            t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
        }
        return;
    }

    il int merge(cs int x,cs int y){
        if(!x||!y) return x+y;
        if(t[x].pri<t[y].pri){
            rs(x)=merge(rs(x),y);
            t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
            return x;
        } 
        else{
            ls(y)=merge(x,ls(y));
            t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
            return y;
        }
    }

    il void del(int &rt,cs int val){
        ri int x,y,z;
        split(rt,val,x,z),split(x,val-1,x,y);
        y=merge(ls(y),rs(y));
        rt=merge(merge(x,y),z);
        return;
    }

    il void ins(int &rt,cs int val){
        ri int x,y;
        split(rt,val,x,y);
        rt=merge(merge(x,add(val)),y);
        return;
    }

    il int rnk(int &rt,cs int val){
        ri int x,y,as;
        split(rt,val-1,x,y);
        as=t[x].sz+1,rt=merge(x,y);
        return as;
    }

    il int kth(cs int rt,int k){
        ri int o=rt;
        while(1){//rt=0
            if(k<=t[ls(o)].sz) o=ls(o);
            else if(k==t[ls(o)].sz+1) return o;//
            else k-=t[ls(o)].sz+1,o=rs(o);//
        }
    }

    il int pre(int &rt,cs int val){
        ri int x,y,as;
        split(rt,val-1,x,y);
        as=t[kth(x,t[x].sz)].val;
        rt=merge(x,y);
        return as;
    }

    il int nxt(int &rt,cs int val){
        ri int x,y,as;
        split(rt,val,x,y);
        as=t[kth(y,1)].val;
        rt=merge(x,y);
        return as;
    }
} using namespace fhq_treap;

signed main(){
    n=rd();
    for(ri int i=1,op,x;i<=n;++i){
        op=rd(),x=rd();
        switch (op){
            case 1: ins(rot,x); break;
            case 2: del(rot,x); break;
            case 3: wn(rnk(rot,x)); break;
            case 4: wn(t[kth(rot,x)].val); break;
            case 5: wn(pre(rot,x)); break;
            default: wn(nxt(rot,x));break;
        }
    }
    return 0;
}

区间翻转

\([l, r]\) 分裂出来(按子树大小),打上懒标记,再合并回去,记得下放懒标记

il void rev(int &rt,int l,int r){
    ri int x,y,z;
    split(rt,r,x,z),split(x,l-1,x,y);
    t[y].lz^=1,rt=merge(merge(x,y),z);
}

\(split\)有一点差异

il void split(cs int rt,cs int k,int &x,int &y){
    if(!rt) x=y=0;
    else{
        pushdown(rt);
        if(t[ls(rt)].sz<k){ //要减去左儿子的size!
            x=rt,split(rs(rt),k-t[ls(rt)].sz-1,rs(x),y);
        }
        else y=rt,split(ls(rt),k,x,ls(y));
        t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
    }
    return;
}

\(merge\) 要在合并前下放标记

il int merge(cs int x,cs int y){//sz[x]<sz[y]
    if(!x||!y) return x+y;
    if(t[x].pri<t[y].pri){
        pushdown(x);
        rs(x)=merge(rs(x),y);
        t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
        return x;
    } 
    else{
        pushdown(y);
        ls(y)=merge(x,ls(y));
        t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
        return y;
    }
}
code
#include <bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define F(s) freopen(#s".in","r",stdin),freopen(#s".out","w",stdout);            
using namespace std;

namespace Q{
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=getchar();
        while(!isdigit(c)) f|=(c==45),c=getchar();
        while(isdigit(c)) x=x*10+(c^48),c=getchar();
        return f?-x:x;
    }
    il void wt(int x){
        if(x<0) x=-x,putchar(45);
        if(x>=10) wt(x/10);
        return putchar(x%10|48),void();
    }
} using namespace Q;

cs int N=1e5+5;
int cnt,rot,n,m;
mt19937 srd(time(0));

namespace fhq_treap{
    #define ls(x) t[x].ch[0]
    #define rs(x) t[x].ch[1]

    struct tree{
        int sz,val,pri,ch[2],lz;
    }t[N<<2];

    il void pushdown(int rt){
        if(t[rt].lz){
            t[rt].lz=0;
            swap(ls(rt),rs(rt));
            t[ls(rt)].lz^=1;
            t[rs(rt)].lz^=1;
        }
    }

    il int add(cs int val){
        t[++cnt].sz=1;
        t[cnt].val=val;
        t[cnt].pri=srd();
        return cnt;
    }

    il void split(cs int rt,cs int k,int &x,int &y){
        if(!rt) x=y=0;
        else{
            pushdown(rt);
            if(t[ls(rt)].sz<k){
                x=rt,split(rs(rt),k-t[ls(rt)].sz-1,rs(x),y);
            }
            else y=rt,split(ls(rt),k,x,ls(y));
            t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
        }
        return;
    }

    il int merge(cs int x,cs int y){//sz[x]<sz[y]
        if(!x||!y) return x+y;
        if(t[x].pri<t[y].pri){
            pushdown(x);
            rs(x)=merge(rs(x),y);
            t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
            return x;
        } 
        else{
            pushdown(y);
            ls(y)=merge(x,ls(y));
            t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
            return y;
        }
    }

    il void rev(int &rt,int l,int r){
        ri int x,y,z;
        split(rt,r,x,z),split(x,l-1,x,y);
        t[y].lz^=1,rt=merge(merge(x,y),z);
    }

    il void prt(int rt){
        pushdown(rt);
        if(ls(rt)) prt(ls(rt));
        wt(t[rt].val),putchar(32);
        if(rs(rt)) prt(rs(rt));
    }
} using namespace fhq_treap;

signed main(){
    n=rd(),m=rd();
    for(ri int i=1;i<=n;++i){
        rot=merge(rot,add(i));
    } 
    for(ri int i=1,l,r;i<=m;++i){
        l=rd(),r=rd(),rev(rot,l,r);
    } 
    prt(rot);
    return 0;
}

edit

posted @ 2023-03-16 09:43  雨夜风月  阅读(47)  评论(0编辑  收藏  举报