其他分享
首页 > 其他分享> > 平衡树板子

平衡树板子

作者:互联网

fhq Treap

#include <bits/stdc++.h>
using namespace std;
#define rg register
#define I inline
#define gc getchar
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define per(i, a, b) for(int i = a; i >= b; --i)
I int read(){
	rg char ch = gc();
	rg int x = 0, f = 0;
	while(!isdigit(ch)) f |= (ch == '-'), ch = gc();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
	return f ? -x : x;
}
const int N = 1e5 + 5;
int n;
int son[N][2], v[N], tot, poe[N], sz[N], root, x, y, z;
#define ls son[p][0]
#define rs son[p][1]
I void up(const int &p){
	sz[p] = sz[ls] + sz[rs] + 1;
}
I int new_node(int a){
	sz[++tot] = 1; poe[tot] = rand(); v[tot] = a;
	return tot;
}
void split(int p, const int k, int &x, int &y){
	if(!p){ x = y = 0; return; }
	if(v[p] <= k){
		x = p;
		split(rs, k, rs, y);
	}else{
		y = p;
		split(ls, k, x, ls);
	}
	up(p);                                                                                                     
} 
int merge(int A, int B){
	if(!A || !B) return A | B;
	if(poe[A] > poe[B]){
		son[A][1] = merge(son[A][1], B);
		up(A);
		return A;
	}
	son[B][0] = merge(A, son[B][0]);
	up(B);
	return B;
}
I void insert(int a){
	split(root, a, x, y);
	root = merge(x, merge(new_node(a), y));
}
I void del(int a){
	split(root, a, x, z);
	split(x, a - 1, x, y);
	y = merge(son[y][0], son[y][1]);
	root = merge(merge(x, y), z);	
}
I int kth(int p, int k){
	if(sz[p] < k) return 0;
	while(true){
		if(sz[ls] >= k) p = ls;
		else if(sz[ls] + 1 == k) return p;
		else k -= sz[ls] + 1, p = rs;
	}
}
I int pre(int a){
	split(root, a - 1, x, y);
	int p = x; while(rs) p = rs;
	root = merge(x, y);
	return p;
}
I int nxt(int a){
	split(root, a, x, y);
	int p = y; while(ls) p = ls;
	root = merge(x, y);
	return p;
}
int main(){
	srand(time(0));
	n = read();
	int op, a;
	while(n--){
		op = read(); a = read();
		switch(op){
			case 1: insert(a); break;
			case 2: del(a); break;
			case 3: 
				split(root, a - 1, x, y);
				printf("%d\n", sz[x] + 1);
				root = merge(x, y);
				break;
			case 4: printf("%d\n", v[kth(root, a)]); break;
			case 5:	printf("%d\n", v[pre(a)]); break;
			case 6: printf("%d\n", v[nxt(a)]); break;
		}
	}
	return 0;
}

Splay

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 1e5 + 5;
#define rg register
#define gc getchar
#define I inline
I int read(){
	rg char ch = gc();
	rg int x = 0, f = 0;
	while(!isdigit(ch)) f |= (ch == '-'), ch = gc();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
	return f ? -x : x;
}
int f[N], sz[N], son[N][2], v[N], cnt[N], tot, root;
#define fs(p) (son[f[p]][1] == p)
#define ls son[p][0]
#define rs son[p][1]
void up(int &p){
	sz[p] = sz[ls] + sz[rs] + cnt[p];
}
I void rot(int &p){
	int fa = f[p], ffa = f[fa];
	int c = fs(p), cc = fs(fa);
	son[fa][c] = son[p][c ^ 1]; f[son[p][c ^ 1]] = fa;
	son[p][c ^ 1] = fa; f[fa] = p;
	if(ffa) son[ffa][cc] = p;//
	f[p] = ffa;	
	up(fa); up(p);
}
I void splay(int p, int goal = 0){
	if(!p) return;
	static int fa, ffa;
	while(f[p] ^ goal){
		fa = f[p], ffa = f[fa];
		if(ffa ^ goal) rot(fs(p) == fs(fa) ? fa : p);
		rot(p);
	}
	if(!goal) root = p;
}
I void find(int x){
	int p = root;
	while(v[p] ^ x && son[p][x > v[p]]) p = son[p][x > v[p]];
	splay(p);
}
I void insert(int x){
	int p = root;
	while(v[p] ^ x && son[p][x > v[p]]) p = son[p][x > v[p]];
	if(v[p] == x){ ++cnt[p]; }
	else{
		++tot;
		if(p) son[p][x > v[p]] = tot;
		f[tot] = p;
		sz[tot] = cnt[tot] = 1;
		v[tot] = x;
		p = tot;
	}
	splay(p);
}
I int pre(int x){
	find(x);
	if(v[root] < x) return root;
	int p = son[root][0];
	while(rs) p = rs;
	return p;
}
int nxt(int x){
	find(x);
	if(v[root] > x) return root;
	int p = son[root][1];
	while(ls) p = ls;
	return p;
}
I void del(int x){
	find(x);
	if(v[root] ^ x) return;
	if(cnt[root] > 1){ --sz[root]; --cnt[root]; return; }
	if(!son[root][0] || !son[root][1]){ root = son[root][0] | son[root][1]; f[root] = 0; return; }
	int last = pre(x), nnxt = nxt(x);
	splay(last); splay(nnxt, last);
	son[nnxt][0] = 0;
}
I int kth(int k){
	int p = root;
	if(sz[p] < k) return 0;
	while(1){
		if(sz[ls] >= k) p = ls;
		else if(sz[ls] + cnt[p] >= k) return p;
		else k -= sz[ls] + cnt[p], p = rs;
	}
}
int n;
int main(){
	ios::sync_with_stdio(0);
    n = read();
    int op, x;
    while(n--){
        op = read(), x = read();
        if(op == 1) insert(x);
        if(op == 2) del(x);
        if(op == 3) find(x), cout << sz[son[root][0]] + 1 << '\n';
        if(op == 4) cout << v[kth(x)] << '\n';
        if(op == 5) cout << v[pre(x)] << '\n';
        if(op == 6) cout << v[nxt(x)] << '\n';
    }
    return 0;
}

替罪羊树

#include<bits/stdc++.h>
using namespace std;
#define rg register
inline int read(){
	rg char ch=getchar();
	rg int x=0,f=0;
	while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}
#define alpha 0.7
struct node{
	int del,cnt,sz,val;
	node *ls,*rs;
	inline bool isbad(){
		return cnt*alpha+5<(ls?ls->cnt:0)||cnt*alpha+5<(rs?rs->cnt:0);
	}
	inline void up(){
		cnt=sz=0;
		if(ls) cnt+=ls->cnt,sz+=ls->sz;
		if(rs) cnt+=rs->cnt,sz+=rs->sz;
		sz+=!del;
		++cnt;
	}
	node(int del,int cnt,int sz,int val,node *ls,node *rs):del(del),cnt(cnt),sz(sz),val(val),ls(ls),rs(rs){}
}*root,**badtag;
inline void dfs(node *p,vector<node*> &v){
	if(!p) return;
	dfs(p->ls,v);
	if(!p->del) v.push_back(p);
	dfs(p->rs,v);
	if(p->del) delete p;
}
inline node* build(int l,int r,vector<node*> &v){
	if(l>r) return NULL;
	int mid=(l+r)>>1;
	node *p=v[mid];
	p->ls=build(l,mid-1,v);
	p->rs=build(mid+1,r,v);
	p->up();
	return p;
}
inline void rebuild(node *&p){
	vector<node*> v;
	dfs(p,v);
	p=build(0,v.size()-1,v);
}
inline void insert(int &x,node *&p){
	if(!p){
		p=new node(0,1,1,x,NULL,NULL);
		return;
	}
	++p->cnt,++p->sz;
	if(x<=p->val) insert(x,p->ls);
	else insert(x,p->rs);
	if(p->isbad()) badtag=&p;
	else if(badtag){
		p->cnt-=(*badtag)->cnt-(*badtag)->sz;
	}
}
inline void insert(int x){
	badtag=NULL;
	insert(x,root);
	if(badtag) rebuild(*badtag);
}
inline int mink(int k){
	node *p=root;
	int ans=1;
	while(p){
		if(p->val<k) ans+=(!p->del+(p->ls?p->ls->sz:0)),p=p->rs;
		else p=p->ls;
	}
	return ans;
}
inline int kth(int k){
	node *p=root;
	while(p){
		if(!p->del&&(p->ls?p->ls->sz:0)+1==k) return p->val;
		if((p->ls?p->ls->sz:0)>=k) p=p->ls;
		else k-=(p->ls?p->ls->sz:0)+!p->del,p=p->rs;
	}
}
inline void erase(int k,node *p){
	while(p){
		--p->sz;
		if(!p->del&&(p->ls?p->ls->sz:0)+1==k){
			p->del=1;
			return;
		}
		if((p->ls?p->ls->sz:0)>=k) p=p->ls;
		else k-=(p->ls?p->ls->sz:0)+!p->del,p=p->rs;
	}
}
int n;
int main(){
	n=read();
	int op,x;
	while(n--){
		op=read(),x=read();
		if(op==1) insert(x);
		else if(op==2) erase(mink(x),root);
		else if(op==3) printf("%d\n",mink(x));
		else if(op==4) printf("%d\n",kth(x));
		else if(op==5) printf("%d\n",kth(mink(x)-1));
		else if(op==6) printf("%d\n",kth(mink(x+1)));
	}
	return 0;
}

标签:sz,cnt,return,int,板子,ls,平衡,root
来源: https://www.cnblogs.com/int256/p/16512269.html