[做題記錄]平衡樹
阿新 • • 發佈:2021-12-05
不敢開啟結果,一開啟,好像什麼都結束了。
記錄一下平衡樹的一些題目。
遇到了新的會更新。
[模板]平衡樹
兩版程式碼。
一版替罪羊。
一版無旋 \(treap\)。
替罪羊還是好寫。
// code by fhq_treap #include<bits/stdc++.h> #define ll long long #define N 300005 #define alpha 0.7 inline ll read(){ char C=getchar(); ll A=0 , F=1; while(('0' > C || C > '9') && (C != '-')) C=getchar(); if(C == '-') F=-1 , C=getchar(); while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar(); return A*F; } template <typename T> void write(T x) { if(x < 0) { putchar('-'); x = -x; } if(x > 9) write(x/10); putchar(x % 10 + '0'); return; } int tot; struct P{ int l,r,v,sz,valid; bool del; inline void Newnode(int x){l = r = 0;sz = valid = 1;del = 0;v = x;} }t[N << 2]; #define ls(o) t[o].l #define rs(o) t[o].r inline bool bad(int o){ return std::max(1.0 * t[ls(o)].sz,1.0 * t[rs(o)].sz) > alpha * t[o].sz; } inline void up(int u){ t[u].sz = t[ls(u)].sz + t[rs(u)].sz + !t[u].del; t[u].valid = t[ls(u)].valid + t[rs(u)].valid + !t[u].del; } inline void dfs(int u,std::vector<int> & v){ if(!u)return ; dfs(ls(u),v); if(!t[u].del)v.push_back(u); dfs(rs(u),v); } inline int build(std::vector<int> &v,int l,int r){ if(l >= r)return 0; #define mid ((l + r) >> 1) int u = v[mid]; ls(u) = build(v,l,mid); rs(u) = build(v,mid + 1,r); up(u); return u; } inline void rebuild(int &u){ std::vector<int>v; dfs(u,v); u = build(v,0,(int)v.size()); } inline void insert(int x,int &u){ if(!u){ u = ++ tot; t[u].Newnode(x); return ; } t[u].sz ++;t[u].valid ++; if(x >= t[u].v)insert(x,rs(u)); else insert(x,ls(u)); if(bad(u)) rebuild(u); return ; } inline int getrank(int u,int x){ int ans = 1; while(u){ if(t[u].v >= x)u = ls(u); else{ ans += t[ls(u)].valid + !t[u].del; u = rs(u); } } return ans; } inline int findkth(int u,int x){ while(u){ if(!t[u].del && t[ls(u)].valid + 1 == x) return t[u].v; if(t[ls(u)].valid >= x) u = ls(u); else{ x -= t[ls(u)].valid + !t[u].del; u = rs(u); } } } inline void Del(int u,int rk){ if(!t[u].del && rk == t[ls(u)].valid + 1){ t[u].del = 1; -- t[u].valid; return; } -- t[u].valid; if(rk <= t[ls(u)].valid + !t[u].del) Del(ls(u),rk); else Del(rs(u),rk - t[ls(u)].valid - !t[u].del); // up(u); } int n,rt; int main(){ scanf("%d",&n); rt = 0; while(n -- ){ int opt,x; scanf("%d%d",&opt,&x); if(opt == 1)insert(x,rt); if(opt == 2)Del(rt,getrank(rt,x)); if(opt == 3)std::cout<<getrank(rt,x)<<std::endl; if(opt == 4)std::cout<<findkth(rt,x)<<std::endl; if(opt == 5)std::cout<<findkth(rt,getrank(rt,x) - 1)<<std::endl; if(opt == 6)std::cout<<findkth(rt,getrank(rt,x + 1))<<std::endl; } }
//rest : 126 days #include<bits/stdc++.h> #define ll long long #define N 100005 int ch[N][2]; ll va[N],key[N]; int siz[N]; inline ll randdom(){return rand() << 15 | rand();} int cnt; #define ls(x) ch[x][0] #define rs(x) ch[x][1] #define v(x) va[x] #define c(x) key[x] #define s(x) siz[x] inline int New(ll s){++cnt;s(cnt) = 1,v(cnt) = s,c(cnt) = randdom();return cnt;} inline void up(int u){s(u) = 1 + s(ls(u)) + s(rs(u));} inline void split(int u,ll k,int &x,int &y){//x,y分裂的兩顆樹,x小於key,y大於key if(!u){x = y = 0;return;} if(v(u) <= k){x = u,split(rs(u),k,rs(u),y);} else{y = u,split(ls(u),k,x,ls(u));} up(u); } inline int merge(int x,int y){//max \in x < min \in y small root if(!x || !y)return x + y; if(c(x) < c(y)) {rs(x) = merge(rs(x),y);up(x);return x;} else {ls(y) = merge(x,ls(y));up(y);return y;} } int root,x,y,z; inline void insert(ll a){ split(root,a,x,y); root = merge(merge(x,New(a)),y); } inline void del(ll a){ split(root,a,x,z); split(x,a - 1,x,y); y = merge(ls(y),rs(y)); root = merge(x,merge(y,z)); } inline int find(ll a){ split(root,a - 1,x,y); int ans = s(x) + 1; root = merge(x,y); return ans; } inline ll kth(int u,ll k){ if(s(ls(u)) >= k)return kth(ls(u),k); if(s(ls(u)) + 1 == k)return u; return kth(rs(u),k - s(ls(u)) - 1); } inline ll pre(ll a){ split(root,a - 1,x,y); ll ans = v(kth(x,s(x))); root = merge(x,y); return ans; } inline ll nex(ll a){ split(root,a,x,y); ll ans = v(kth(y,1)); root = merge(x,y); return ans; } int n; int main(){ scanf("%d",&n); for(int i = 1;i <= n;++i){ int opt; ll x; scanf("%d%lld",&opt,&x); if(opt == 1)insert(x); if(opt == 2)del(x); if(opt == 3)std::cout<<find(x)<<std::endl; if(opt == 4)std::cout<<v(kth(root,x))<<std::endl; if(opt == 5)std::cout<<pre(x)<<std::endl; if(opt == 6)std::cout<<nex(x)<<std::endl; } }