1. 程式人生 > 其它 >[做題記錄]平衡樹

[做題記錄]平衡樹

不敢開啟結果,一開啟,好像什麼都結束了。

記錄一下平衡樹的一些題目。
遇到了新的會更新。

[模板]平衡樹

兩版程式碼。
一版替罪羊。
一版無旋 \(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;
	}
}