1. 程式人生 > 其它 >「演算法筆記」FHQ-Treap

「演算法筆記」FHQ-Treap

FHQ-Treap 的操作都以分裂、合併為基礎。 例如插入就是先把樹分裂成兩半,然後把這兩半和新節點分別合併。 區間修改只需分裂出這個區間,然後打個標記合併即可。

右轉→https://www.cnblogs.com/mytqwqq/p/15057231.html

密碼可以來找我要鴨 qwq

下面放個分板子

P3369 【模板】普通平衡樹

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,op,x;
struct Treap{
    int rt,tot,lc[N],rc[N],val[N],sz[N],rnd[N];
    void upd(int x){
        sz[x]=sz[lc[x]]+sz[rc[x]]+1;
    } 
    int getnew(int
k){ val[++tot]=k,rnd[tot]=rand(),sz[tot]=1; return tot; } void split(int p,int &x,int &y,int k){ if(!p){x=y=0;return ;} if(val[p]<=k) x=p,split(rc[p],rc[p],y,k); else y=p,split(lc[p],x,lc[p],k); upd(p); } int merge(int x,int y){ //
前提:x 的權值全部 < y 的權值 if(!x||!y) return x+y; if(rnd[x]<rnd[y]){rc[x]=merge(rc[x],y),upd(x);return x;} else lc[y]=merge(x,lc[y]),upd(y); return y; } void insert(int k){ int x=0,y=0; split(rt,x,y,k),rt=merge(merge(x,getnew(k)),y); } void
erase(int k){ int x=0,y=0,z=0; split(rt,x,z,k),split(x,x,y,k-1); rt=merge(merge(x,merge(lc[y],rc[y])),z); } int rank(int k){ int x=0,y=0,ans; split(rt,x,y,k-1),ans=sz[x]+1,rt=merge(x,y); return ans; } int kth(int rt,int k){ if(!rt) return 0; if(sz[lc[rt]]+1==k) return rt; if(sz[lc[rt]]+1>k) return kth(lc[rt],k); return kth(rc[rt],k-sz[lc[rt]]-1); } int pre(int k){ int x=0,y=0,ans; split(rt,x,y,k-1),ans=kth(x,sz[x]),rt=merge(x,y); return ans; } int nxt(int k){ int x=0,y=0,ans; split(rt,x,y,k),ans=kth(y,1),rt=merge(x,y); return ans; } }T; signed main(){ srand(time(0)); scanf("%d",&n); while(n--){ scanf("%d%d",&op,&x); if(op==1) T.insert(x); else if(op==2) T.erase(x); else if(op==3) printf("%d\n",T.rank(x)); else if(op==4) printf("%d\n",T.val[T.kth(T.rt,x)]); else if(op==5) printf("%d\n",T.val[T.pre(x)]); else printf("%d\n",T.val[T.nxt(x)]); } return 0; }

P3391 【模板】文藝平衡樹

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,l,r;
struct Treap{
    int rt,tot,lc[N],rc[N],val[N],sz[N],rnd[N],rev[N];
    void pushup(int x){
        sz[x]=sz[lc[x]]+sz[rc[x]]+1;
    } 
    void pushdown(int x){
        if(!rev[x]) return ;
        swap(lc[x],rc[x]),rev[lc[x]]^=1,rev[rc[x]]^=1;
        rev[x]=0;
    }
    int getnew(int k){
        val[++tot]=k,rnd[tot]=rand(),sz[tot]=1;
        return tot;
    }
    void split(int p,int &x,int &y,int k){    //按子樹大小分裂
        if(!p){x=y=0;return ;}
        pushdown(p);
        if(sz[lc[p]]+1<=k) x=p,split(rc[p],rc[p],y,k-sz[lc[p]]-1);
        else y=p,split(lc[p],x,lc[p],k);
        pushup(p);
    }
    int merge(int x,int y){
        if(!x||!y) return x+y;
        if(rnd[x]<rnd[y]){
            pushdown(x),rc[x]=merge(rc[x],y),pushup(x);
            return x;
        }
        else pushdown(y),lc[y]=merge(x,lc[y]),pushup(y);
        return y;
    } 
}T;
void print(int x){
    T.pushdown(x);
    if(T.lc[x]) print(T.lc[x]);
    printf("%d ",T.val[x]);
    if(T.rc[x]) print(T.rc[x]);
}
signed main(){
    srand(time(0));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        T.rt=T.merge(T.rt,T.getnew(i));
    while(m--){
        scanf("%d%d",&l,&r);
        int x=0,y=0,z=0;
        T.split(T.rt,x,y,l-1),T.split(y,y,z,r-l+1);
        T.rev[y]^=1,T.rt=T.merge(x,T.merge(y,z));
    }
    print(T.rt);
    return 0;
}
轉載請註明原文連結