「演算法筆記」FHQ-Treap
阿新 • • 發佈:2021-07-25
FHQ-Treap 的操作都以分裂、合併為基礎。
例如插入就是先把樹分裂成兩半,然後把這兩半和新節點分別合併。
區間修改只需分裂出這個區間,然後打個標記合併即可。
右轉→https://www.cnblogs.com/mytqwqq/p/15057231.html
密碼可以來找我要鴨 qwq
下面放個分板子
#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(intk){ 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); } voiderase(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; }
#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; }轉載請註明原文連結