【模板】平衡树

\(\Large\text{原题}\)

\(\Large\text{有旋}TREAP\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
template<int the_size>
class TREAP {
	private : 
		struct TREE {
			int lid, rid;
			int val, data;
			int size, cnt;
		} tree[the_size];
		int tot;
		int ans, ROOT;
		#define lid(id) tree[id].lid
		#define rid(id) tree[id].rid
		#define val(id) tree[id].val
		#define data(id) tree[id].data
		#define size(id) tree[id].size
		#define cnt(id) tree[id].cnt
		void pushup(int id) {
			size(id) = size(lid(id))+size(rid(id))+cnt(id);
		}//上传;
		void newnode(int id,int v) {
			size(id) = cnt(id) = 1;
			val(id) = v;
			data(id) = rand();
		}
		void zip(int &id) {
			int tmp = rid(id);
			rid(id) = lid(tmp);
			lid(tmp) = id;
			size(tmp) = size(id);
			pushup(id);
			id = tmp;
		}
		void zap(int &id) {
			int tmp = lid(id);
			lid(id) = rid(tmp);
			rid(tmp) = id;
			size(tmp) = size(id);
			pushup(id);
			id = tmp;
		}
		void conduct_insert(int &id,int v) {
			if(!id) {
				id = ++tot;
				newnode(id,v);
				return;
			}
			size(id)++;
			if(val(id) == v) {
				cnt(id)++;
			} else if(val(id) < v) {
				conduct_insert(rid(id),v);
				if(data(rid(id)) < data(id)) 
					zip(id);
			} else {
				conduct_insert(lid(id),v);
				if(data(lid(id)) < data(id)) 
					zap(id);
			}
		}
		bool conduct_delete(int &id,int v) {
			if(!id) return false;
			if(val(id) == v) {
				if(cnt(id) > 1) {
					cnt(id)--;
					size(id)--;
					return true;
				}
				if(lid(id) == 0||rid(id) == 0) {
					id = lid(id)+rid(id);
					//把左或右子树上提;
					return true;
				} else if(data(lid(id)) < data(rid(id))) {
					zap(id);
					return conduct_delete(id,v);
				} else {
					zip(id);
					return conduct_delete(id,v);
				}
			} else if(val(id) < v) {
				bool success_key = conduct_delete(rid(id),v);
				if(success_key) size(id)--;
				return success_key;
			} else {
				bool success_key = conduct_delete(lid(id),v);
				if(success_key) size(id)--;
				return success_key;
			}
		}
		int Get_Rank(int id,int v) {
			if(!id) return 0;
			if(val(id) == v) {
				return size(lid(id))+1;
			} else if(v > val(id)) {
				return size(lid(id))+cnt(id)+Get_Rank(rid(id),v);
			} else {
				return Get_Rank(lid(id),v);
			}
		}
		int Get_Number(int id,int k) {
			if(!id) return 0;
			if(k <= size(lid(id))) {
				return Get_Number(lid(id),k);
			} else if(k > size(lid(id))+cnt(id)) {
				return Get_Number(rid(id),k-size(lid(id))-cnt(id));
			} else {
				return val(id);
			}
		}
		void conduct_pre(int id,int v) {
			if(!id) return;
			if(val(id) < v) {
				ans = id;
				conduct_pre(rid(id),v);
			} else {
				conduct_pre(lid(id),v);
			}
		}
		void conduct_suc(int id,int v) {
			if(!id) return;
			if(val(id) > v) {
				ans = id;
				conduct_suc(lid(id),v);
			} else {
				conduct_suc(rid(id),v);
			}
		}
		#undef lid
		#undef rid
		#undef val
		#undef data
		#undef size
		#undef cnt
	public : 
		void init() {
			tot = ROOT = 0;
		}
		void Insert(int v) {
			conduct_insert(ROOT,v);
		}
		void Delete(int v) {
			conduct_delete(ROOT,v);
		}
		int Rank(int v) {
			return Get_Rank(ROOT,v);
		}
		int Number(int k) {
			return Get_Number(ROOT,k);
		}
		int Pre(int v) {
			ans = 0;
			conduct_pre(ROOT,v);
			return tree[ans].val;
		}
		int Suc(int v) {
			ans = 0;
			conduct_suc(ROOT,v);
			return tree[ans].val;
		}
};
TREAP<1000010> treap;
void work_P3369() {
	treap.init();
	srand('b'+'i'+'k'+'u');
	int n;
	scanf("%d",&n);
	for(int i = 1, opt, x;i <= n;++i) {
		scanf("%d %d",&opt,&x);
		switch(opt) {
			case 1 : 
				treap.Insert(x);
				break;
			case 2 : 
				treap.Delete(x);
				break;
			case 3 : 
				printf("%d\n",treap.Rank(x));
				break;
			case 4 : 
				printf("%d\n",treap.Number(x));
				break;
			case 5 : 
				printf("%d\n",treap.Pre(x));
				break;
			case 6 : 
				printf("%d\n",treap.Suc(x));
				break;
		}
	}
}
signed main() {
	work_P3369();
}

\(\Large\text{无旋}TREAP\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
enum {
	the_size = 100010
};
class TREAP {
	private : 
		struct TREE {
			int lid, rid;
			int value, data;
			int size;
		} tree[the_size];
		int tot, ROOT;
		#define lid(id) tree[id].lid
		#define rid(id) tree[id].rid
		#define val(id) tree[id].value
		#define data(id) tree[id].data
		#define size(id) tree[id].size
		void update(int id) {
			size(id) = size(lid(id))+size(rid(id))+1;
		}
		int new_node(int v) {
			size(++tot) = 1;
			val(tot) = v;
			data(tot) = rand();
			return tot;
		}
		int merge(int a,int b) {
			if(!a||!b) return a+b;
			if(data(a) < data(b)) {
				rid(a) = merge(rid(a),b);
				update(a);
				return a;
			} else {
				lid(b) = merge(a,lid(b));
				update(b);
				return b;
			}
		}
		void split(int id,int k,int &a,int &b) {
			if(!id) 
				a = b = 0;
			else {
				if(val(id) <= k) {
					a = id;
					split(rid(id),k,rid(id),b);
				} else {
					b = id;
					split(lid(id),k,a,lid(id));
				}
				update(id);
			}
		}
		int conduct_rank(int id,int k) {
			while(1) {
				if(k <= size(lid(id))) {
					id = lid(id);
				} else if(k == size(lid(id))+1) {
					return id;
				} else {
					k -= size(lid(id))+1;
					id = rid(id);
				}
			}
		}
	public : 
		void Init() {
			srand(time(0));
			tot = ROOT = 0;
		}
		void Insert(int v) {
			int a, b;
			split(ROOT,v,a,b);
			ROOT = merge(merge(a,new_node(v)),b);
		}
		void Delete(int v) {
			int a, b, c;
			split(ROOT,v,a,c);
			split(a,v-1,a,b);
			b = merge(lid(b),rid(b));
			ROOT = merge(merge(a,b),c);
		}
		int Rank(int v) {
			int a, b;
			split(ROOT,v-1,a,b);
			int ans = size(a)+1;
			ROOT = merge(a,b);
			return ans;
		}
		int Number(int k) {
			return tree[conduct_rank(ROOT,k)].value;
		}
		int Pre(int v) {
			int a, b;
			split(ROOT,v-1,a,b);
			int ans = tree[conduct_rank(a,size(a))].value;
			ROOT = merge(a,b);
			return ans;
		}
		int Suc(int v) {
			int a, b;
			split(ROOT,v,a,b);
			int ans = tree[conduct_rank(b,1)].value;
			ROOT = merge(a,b);
			return ans;
		}
} treap;
void work_P3369() {
    treap.Init();
    int n;
    scanf("%d",&n);
    for(int i = 1, opt, x;i <= n;++i) {
        scanf("%d %d",&opt,&x);
        switch(opt) {
            case 1 : 
                treap.Insert(x);
                break;
            case 2 : 
                treap.Delete(x);
                break;
            case 3 : 
                printf("%d\n",treap.Rank(x));
                break;
            case 4 : 
                printf("%d\n",treap.Number(x));
                break;
            case 5 : 
                printf("%d\n",treap.Pre(x));
                break;
            case 6 : 
                printf("%d\n",treap.Suc(x));
                break;
        }
    }
}
signed main() {
    work_P3369();
}

\(\Large SPLAY\)

点击查看代码
#include <cstdio>
using namespace std;
enum {
	the_size = 100010
};
class SPLAY {
	private : 
		struct TREE {
			int cid[2], pid;
			int val;
			int size, cnt;
		} tree[the_size];
		#define cid(id,which) tree[id].cid[which]
		#define rid(id) tree[id].cid[1]
		#define lid(id) tree[id].cid[0]
		#define pid(id) tree[id].pid
		#define val(id) tree[id].val
		#define size(id) tree[id].size
		#define cnt(id) tree[id].cnt
		int tree_tot, ROOT;
		void initial() {
			tree_tot = ROOT = 0;
		}
		void pushup(int id) {
			size(id) = size(cid(id,0))+size(cid(id,1))+cnt(id);
		}
		bool get(int id) {
			return id == rid(pid(id));
			//if id is pid(id)'s right son return 1;
			//else return 0;
		}
		void clear(int id) {
			lid(id) = rid(id) = pid(id) = val(id) = size(id) = cnt(id) = 0;
		}
		void _rorate(int id) {
			int f = pid(id), g = pid(f), ch = get(id);
			cid(f,ch) = cid(id,ch^1);
			if(cid(id,ch^1)) pid(cid(id,ch^1)) = f;
			cid(id,ch^1) = f;
			pid(f) = id;
			pid(id) = g;
			if(g) cid(g,f == cid(g,1)) = id;
			pushup(f);
			pushup(id);
		}
		void _splay(int id) {
			for(int f = pid(id);f = pid(id), f;_rorate(id)) 
				if(pid(f)) _rorate(get(id) == get(f) ? f : id);
			ROOT = id;
			//把id旋转到根节点;
		}
		void conduct_insert(int v) {
			if(!ROOT) {
				val(++tree_tot) = v;
				cnt(tree_tot)++;
				ROOT = tree_tot;
				pushup(ROOT);
				return;
			}
			int id = ROOT, f = 0;
			while(1) {
				if(val(id) == v) {
					cnt(id)++;
					pushup(id);
					pushup(f);
					_splay(id);
					break;
				}
				f = id;
				id = cid(id,val(id) < v);
				if(!id) {
					id = ++tree_tot;
					val(id) = v;
					cnt(id)++;
					pid(id) = f;
					cid(f,val(f) < v) = id;
					pushup(id);
					pushup(f);
					_splay(id);
					break;
				}
			}
		}
		int conduct_rank(int v) {
			int res = 0;
			int id = ROOT;
			while(1) {
				if(v < val(id)) {
					id = lid(id);
				} else {
					res += size(lid(id));
					if(v == val(id)) {
						_splay(id);
						return res+1;
					}
					res += cnt(id);
					id = rid(id);
				}
			}
		}
		int conduct_number(int k) {
			int id = ROOT;
			while(1) {
				if(lid(id)&&k <= size(lid(id))) {
					id = lid(id);
				} else {
					k -= cnt(id)+size(lid(id));
					if(k <= 0) {
						_splay(id);
						return val(id);
					}
					id = cid(id,1);
				}
			}
		}
		int conduct_pre() {
			int id = lid(ROOT);
			if(!id) return id;
			while(rid(id)) id = rid(id);
			_splay(id);
			return id;
		}
		int conduct_suc() {
			int id = rid(ROOT);
			if(!id) return id;
			while(lid(id)) id = lid(id);
			_splay(id);
			return id;
		}
		void conduct_delete(int v) {
			conduct_rank(v);
			int id = ROOT;
			if(cnt(id) > 1) {
				cnt(id)--;
				pushup(id);
				return;
			}
			if(!lid(id)&&!rid(id)) {
				clear(id);
				ROOT = 0;
				return;
			}
			if(!lid(id)) {
				ROOT = rid(ROOT);
				pid(ROOT) = 0;
				clear(id);
				return;
			}
			if(!rid(id)) {
				ROOT = lid(ROOT);
				pid(ROOT) = 0;
				clear(id);
				return;
			}
			int x = conduct_pre();
			pid(rid(id)) = x;
			rid(x) = rid(id);
			clear(id);
			pushup(ROOT);
		}
		#undef cid
		#undef rid
		#undef lid
		#undef pid
		#undef val
		#undef size
		#undef cnt
	public : 
		void Init() {
			initial();
		}
		void Insert(int v) {
			conduct_insert(v);
		}
		void Delete(int v) {
			conduct_delete(v);
		}
		int Rank(int v) {
			return conduct_rank(v);
		}
		int Number(int k) {
			return conduct_number(k);
		}
		int Pre(int v) {
			conduct_insert(v);
			int ans = conduct_pre();
			conduct_delete(v);
			return tree[ans].val;
		}
		int Suc(int v) {
			conduct_insert(v);
			int ans = conduct_suc();
			conduct_delete(v);
			return tree[ans].val;
		}
} splay;
void work_P3369() {
	splay.Init();
	int n;
	scanf("%d",&n);
	for(int i = 1, opt, x;i <= n;++i) {
		scanf("%d %d",&opt,&x);
		switch(opt) {
			case 1 : 
				splay.Insert(x);
				break;
			case 2 : 
				splay.Delete(x);
				break;
			case 3 : 
				printf("%d\n",splay.Rank(x));
				break;
			case 4 : 
				printf("%d\n",splay.Number(x));
				break;
			case 5 : 
				printf("%d\n",splay.Pre(x));
				break;
			case 6 : 
				printf("%d\n",splay.Suc(x));
				break;
		}
	}
}
signed main() {
	work_P3369();
}

\(\Large 01TRIE\)

点击查看代码
#include <cstdio>
using namespace std;
const int max_log = 25;
const int the_size = 1e5+10;
const int num = 10000000;
struct zero_one_TRIE {
	int tot;
	int sid[the_size*max_log][2];
	int size[the_size*max_log];
	void init() {
		sid[1][0] = sid[1][1] = 0;
		tot = 2;
	}
	int New_Node() {
		sid[tot][1] = sid[tot][0] = size[tot] = 0;
		return tot++;
	}
	void Insert(int val,int ts) {
		int u = 1;
		for(int i = max_log-1;i >= 0;--i) {
			int v = (val>>i)&1;
			if(!sid[u][v]) sid[u][v] = New_Node();
			u = sid[u][v];
			size[u] += ts;
		}
	}
	int Get_Num(int k) {
		int u = 1, x = 0;
		for(int i = max_log-1;i >= 0;--i) {
			if(size[sid[u][0]] >= k) 
				u = sid[u][0];
			else {
				x |= (1<<i);
				k -= size[sid[u][0]];
				u = sid[u][1];
			}
		}
		return x;
	}
	int Get_Rank(int x) {
		int u = 1, k = 0;
		for(int i = max_log-1;i >= 0;--i) {
			if((x>>i)&1) {
				k += size[sid[u][0]];
				u = sid[u][1];
			} else u = sid[u][0];
		}
		return k;
	}
	int Get_Pre(int x) {
		int w = Get_Num(Get_Rank(x));
		return w;
	}
	int Get_Nex(int x) {
		int y = Get_Num(Get_Rank(x+1)+1);
		return y;
	}
} trie;
int n, opt, x, ans;
signed main() {
	trie.init();
	scanf("%d",&n);
	for(int i = 1;i <= n;++i) {
		scanf("%d %d",&opt,&x);
		switch(opt) {
			case 1 :
				trie.Insert(x+num,1);
				break;
			case 2 :
				trie.Insert(x+num,-1);
				break;
			case 3 :
				ans = trie.Get_Rank(x+num)+1;
				printf("%d\n",ans);
				break;
			case 4 :
				ans = trie.Get_Num(x)-num;
				printf("%d\n",ans);
				break;
			case 5 :
				ans = trie.Get_Pre(x+num)-num;
				printf("%d\n",ans);
				break;
			case 6 :
				ans = trie.Get_Nex(x+num)-num;
				printf("%d\n",ans);
				break;
		}
	}
}

\(\Large\text{朝鲜树}\)

点击查看代码
#include <cstdio> 
#include <algorithm>
using namespace std;
const int Z = 1e5+10;
struct KT {
	int lid, rid;
	int val, size;
	int cnt;
	int depth;
	int great;
	bool operator < (const KT x) {
		return val < x.val;
	}
} tree[Z];
int TOT, ROOT;
#define lid(id) tree[id].lid
#define rid(id) tree[id].rid
#define val(id) tree[id].val
#define size(id) tree[id].size
#define cnt(id) tree[id].cnt
#define dep(id) tree[id].depth
#define est(id) tree[id].great
void Push_Up(int id) {
	size(id) = size(lid(id))+size(rid(id))+cnt(id);
	est(id) = max(est(lid(id)),est(rid(id)));
}
int Construct(int l,int r,int depth) {
	if(l > r) return 0;
	int mid = (l+r)>>1;
	lid(mid) = Construct(l,mid-1,depth+1);
	rid(mid) = Construct(mid+1,r,depth+1);
	dep(mid) = depth;
	Push_Up(mid);
	return mid;
}
void Re_construct() {
	sort(tree+1,tree+1+TOT);
	ROOT = Construct(1,TOT,1);
}
void Insert(int &id,int v,int depth) {
	if(id == 0) {
		id = ++TOT;
		size(id) = cnt(id) = 1;
		val(id) = v;
		dep(id) = est(id) = depth;
		return;
	}
	if(val(id) == v) {
		cnt(id)++;
		size(id)++;
	} else if(val(id) < v) {
		Insert(rid(id),v,depth+1);
		Push_Up(id);
	} else {
		Insert(lid(id),v,depth+1);
		Push_Up(id);
	}
}
int Get_Min(int &id) {
	if(lid(id)) {
		int res = Get_Min(lid(id));
		Push_Up(id);
		return res;
	}
	int res = id;
	id = rid(id);
	return res;
}
void Delete(int &id,int v) {
	if(val(id) == v) {
		if(cnt(id) > 1) {
			cnt(id)--;
			size(id)--;
			return;
		} else {
			if(lid(id) == 0) {
				id = rid(id);
				return;
			}
			if(rid(id) == 0) {
				id = lid(id);
				return;
			}
			int gm = Get_Min(rid(id));
			val(id) = val(gm);
			cnt(id) = cnt(gm);
			Push_Up(id);
			return;
		}
	} else if(val(id) < v) {
		Delete(rid(id),v);
		Push_Up(id);
		return;
	} else {
		Delete(lid(id),v);
		Push_Up(id);
		return;
	}
}
int Get_Rank(int id,int k) {
	if(val(id) == k) 
		return size(lid(id))+1;
	else if(val(id) < k) 
		return size(lid(id))+cnt(id)+Get_Rank(rid(id),k);
	else 
		return Get_Rank(lid(id),k);
}
int Get_Num(int id,int k) {
	if(size(lid(id))+1 <= k&&size(lid(id))+cnt(id) >= k) 
		return val(id);
	else if(size(lid(id))+1 > k) 
		return Get_Num(lid(id),k);
	else if(size(lid(id))+cnt(id) < k) 
		return Get_Num(rid(id),k-size(lid(id))+cnt(id));
}
int Get_Pre(int id,int v) {
	int s = id, ans;
	while(s) {
		if(v <= val(s)) 
			s = lid(s);
		else {
			ans = s;
			s = rid(s);
		}
	}
	return val(ans);
}
int Get_Suc(int id,int v) {
	int s = id, ans;
	while(s) {
		if(v >= val(s)) 
			s = rid(s);
		else {
			ans = s;
			s = lid(s);
		}
	}
	return val(ans);
}
int n, opt, x;
signed main() {
	scanf("%d",&n);
	for(int outs = 1;outs <= n;++outs) {
		scanf("%d %d",&opt,&x);
		switch(opt) {
			case 1 :
				Insert(ROOT,x,1);
				break;
			case 2 :
				Delete(ROOT,x);
				break;
			case 3 :
				printf("%d\n",Get_Rank(ROOT,x));
				break;
			case 4 :
				printf("%d\n",Get_Num(ROOT,x));
				break;
			case 5 :
				printf("%d\n",Get_Pre(ROOT,x));
				break;
			case 6 :
				printf("%d\n",Get_Suc(ROOT,x));
				break;
		}
		if(est(ROOT) > 100) Re_construct();
	}
}

\(\Large\textbf{树状数组实现}\)

\(\Large vector\text{实现}\)

\(\Large\text{替罪羊树}\)

替罪羊树实现

替罪羊树就是,啊,一旦不平衡了就重建
如何判断平不平衡呢,靠一个平衡因子\(\alpha\)
在如下代码里,\(\alpha\)设为了\(0.8\)
设节点大小(节点数)为\(size_i\),数字大小(数字个数)为\(csize_i\),未删除节点大小(未被完全删除节点个数)为\(dsize_i\)
如果

  1. 这个节点没被删
  2. 这个节点的一个子节点的子树的\(size\)大于本节点\(size\times\alpha\) 或者 该节点\(dsize \le \alpha\times size\)

重构该节点及其子树。

点击查看代码
#include <stdio.h>
template <typename Tec>
Tec max(Tec x,Tec y) {
	return x < y ? y : x;
}
enum {
	the_size = 1000010
};
class SGTREE {
	private : 
		struct SGNODE {
			int lid, rid;
			int key, cnt;
			int size, csize, dsize;
		} tree[the_size];
		int ROOT, tot;
		int flt[the_size];
		double alpha = 0.8;
		#define lid(id) tree[id].lid
		#define rid(id) tree[id].rid
		#define key(id) tree[id].key
		#define cnt(id) tree[id].cnt
		#define size(id) tree[id].size
		#define csize(id) tree[id].csize
		#define dsize(id) tree[id].dsize
		int newnode(int v) {
			tot++;
			key(tot) = v;
			lid(tot) = rid(tot) = 0;
			cnt(tot) = size(tot) = csize(tot) = dsize(tot) = 1;
			return tot;
		}
		void update(int id) {
			size(id) = size(lid(id))+size(rid(id))+1;
			csize(id) = csize(lid(id))+csize(rid(id))+cnt(id);
			dsize(id) = dsize(lid(id))+dsize(rid(id))+(cnt(id) != 0);
		}
		bool judge(int id) {
			return cnt(id) && 
				(alpha*size(id) <= (double)max(size(lid(id)),size(rid(id)))
				|| (double) dsize(id) <= alpha*size(id));
		}
		void flatten(int &ldr,int id) {
			if(!id) return;
			flatten(ldr,lid(id));
			if(cnt(id)) 
				flt[ldr++] = id;
			flatten(ldr,rid(id));
		}
		int recon(int l,int r) {
			int mid = (l+r)>>1;
			if(l >= r) return 0;
			lid(flt[mid]) = recon(l,mid);
			rid(flt[mid]) = recon(mid+1,r);
			update(flt[mid]);
			return flt[mid];
		}
		void reconstruct(int &id) {
			int ldr = 0;
			flatten(ldr,id);
			id = recon(0,ldr);
		}
		void conduct_insert(int &id,int v) {
			if(!id) {
				id = newnode(v);
			} else {
				if(key(id) == v) {
					cnt(id)++;
				} else if(key(id) < v) {
					conduct_insert(rid(id),v);
				} else {
					conduct_insert(lid(id),v);
				}
				update(id);
				if(judge(id)) 
					reconstruct(id);
			}
		}
		void conduct_delete(int &id,int v) {
			if(!id) 
				return;
			else {
				if(key(id) == v) {
					if(cnt(id)) cnt(id)--;
				} else if (key(id) < v) {
					conduct_delete(rid(id),v);
				} else {
					conduct_delete(lid(id),v);
				}
				update(id);
				if(judge(id)) 
					reconstruct(id);
			}
		}
		int conduct_number(int &id,int k) {
			if(!id) 
				return 0;
			else if(csize(lid(id)) < k&&k <= csize(lid(id))+cnt(id)) 
				return key(id);
			else if(csize(lid(id))+cnt(id) < k) 
				return conduct_number(rid(id),k-csize(lid(id))-cnt(id));
			else 
				return conduct_number(lid(id),k);
		}
		int conduct_UB(int &id,int v) {
			if(!id) 
				return 1;
			else if(key(id) == v&&cnt(id)) 
				return csize(lid(id))+cnt(id)+1;
			else if(v < key(id)) 
				return conduct_UB(lid(id),v);
			else 
				return csize(lid(id))+cnt(id)+conduct_UB(rid(id),v);
		}
		int conduct_LB(int &id,int v) {
			//Although it's not "lower_bound" ...;
			if(!id) 
				return 0;
			else if(key(id) == v&&cnt(id)) 
				return csize(lid(id));
			else if(v < key(id)) 
				return conduct_LB(lid(id),v);
			else 
				return csize(lid(id))+cnt(id)+conduct_LB(rid(id),v);
		}
	public : 
		void Init() {
			tot = 0, ROOT = 0;
			lid(ROOT) = rid(ROOT) = 0;
			size(ROOT) = cnt(ROOT) = 0;
		}
		void Insert(int v) {
			conduct_insert(ROOT,v);
		}
		void Delete(int v) {
			conduct_delete(ROOT,v);
		}
		int Number(int k) {
			return conduct_number(ROOT,k);
		}
		int Rank(int k) {
			return conduct_LB(ROOT,k)+1;
		}
		int Upper_Bound(int v) {
			return conduct_UB(ROOT,v);
		}
		int aUpper_Bound(int v) {
			return conduct_LB(ROOT,v);
		}
		int Pre(int v) {
			return conduct_number(ROOT,conduct_LB(ROOT,v));
		}
		int Suc(int v) {
			return conduct_number(ROOT,conduct_UB(ROOT,v));
		}
		void puttree(int id) {
			if(!id) 
				return;
			printf(" > %d %d ( %d ) ( %d )\n",id,key(id),lid(id),rid(id));
			printf("		%d %d %d %d\n",size(id),csize(id),dsize(id),cnt(id));
			puttree(lid(id));
			puttree(rid(id));
		}
		void output() {
			printf(" ROOT :: %d\n",ROOT);
			puttree(ROOT);
		}
} sgt;
void work_P3369() {
	sgt.Init();
	int n;
	scanf("%d",&n);
	for(int i = 1, opt, x;i <= n;++i) {
		scanf("%d %d",&opt,&x);
		switch(opt) {
			case 1 : 
				sgt.Insert(x);
				break;
			case 2 : 
				sgt.Delete(x);
				break;
			case 3 : 
				printf("%d\n",sgt.Rank(x));
				break;
			case 4 : 
				printf("%d\n",sgt.Number(x));
				break;
			case 5 : 
				printf("%d\n",sgt.Pre(x));
				break;
			case 6 : 
				printf("%d\n",sgt.Suc(x));
				break;
			case 7 : 
				sgt.output();
				break;
		}
	}
}
signed main() {
	work_P3369();
}

\(\Large AVL\ \text{树}\)

AVL树实现

AVL树是一种高度平衡的数,要求左右孩子高度差不过1。
为此他用到了左旋,右旋,左左旋,右右旋。
在插入删除后,进行旋转,保证高度差不超过1。
当然得分类讨论。

点击查看代码
#include <algorithm>
#include <stdio.h>
enum {
	the_size = 100010
};
class AVL {
	private : 
		struct TREE {
			int key, cnt;
			int lid, rid;
			int height, size;
		} tree[the_size];
		int tot, ROOT;
		#define key(id) tree[id].key
		#define pid(id) tree[id].pid
		#define lid(id) tree[id].lid
		#define rid(id) tree[id].rid
		#define h(id) tree[id].height
		#define cnt(id) tree[id].cnt
        #define size(id) tree[id].size
		#define max_height(x,y) (std :: max(h(x),h(y)))
		int newnode(int v) {
			key(++tot) = v;
			lid(tot) = rid(tot) = 0;
			h(tot) = size(tot) = cnt(tot) = 1;
			return tot;
		}
		int update(int id) {
            size(id) = size(lid(id))+size(rid(id))+cnt(id);
			h(id) = max_height(lid(id),rid(id))+1;
			return h(id);
		}
		void zig(int &id) {
            int cs = rid(id);
            rid(id) = lid(cs);
            lid(cs) = id;
            update(id);
            update(cs);
            id = cs;
		}
		void zag(int &id) {
            int cs = lid(id);
            lid(id) = rid(cs);
            rid(cs) = id;
            update(id);
            update(cs);
            id = cs;
		}
        void zigzag(int &id) {
            zag(rid(id));
            zig(id);
        }
        void zagzig(int &id) {
            zig(lid(id));
            zag(id);
        }
		void conduct_insert(int &id,int v) {
            if(!id) {
                id = newnode(v);
                return;
            }
            if(key(id) == v) {
                ++cnt(id);
                update(id);
                return;
            }
            if(key(id) < v) {
                conduct_insert(rid(id),v);
                update(id);
                if(h(rid(id))-h(lid(id)) >= 2) {
                    if(v > key(rid(id))) 
                        zig(id);
                    else
                        zigzag(id);
				}
            } else {
                conduct_insert(lid(id),v);
                update(id);
                if(h(lid(id))-h(rid(id)) >= 2) {
                    if(v < key(lid(id))) 
                        zag(id);
                    else
                        zagzig(id);
				}
            }
            update(id);
		}
		void conduct_delete(int &id,int v) {
			if(!id) return;
            if(key(id) > v) {
                conduct_delete(lid(id),v);
                update(id);
                if(h(rid(id))-h(lid(id)) >= 2) {
                    if(h(rid(rid(id))) >= h(rid(lid(id)))) 
                        zig(id);
                    else 
                        zigzag(id);
                }
            } else if(key(id) < v) { 
                conduct_delete(rid(id),v);
                update(id);
                if(h(lid(id))-h(rid(id)) >= 2) {
                    if(h(lid(lid(id))) >= h(lid(rid(id)))) 
                        zag(id);
                    else
                        zagzig(id);
                }
            } else {
                if(cnt(id) > 1) {
                    cnt(id)--;
                    update(id);
                    return;
                }
                if(lid(id)&&rid(id)) {
                    int cur = rid(id);
                    while(lid(cur)) cur = lid(cur);
                    cnt(id) = cnt(cur);
                    key(id) = key(cur);
                    cnt(cur) = 1;
                    conduct_delete(rid(id),key(cur));
                    update(id);
                    if(h(lid(id))-h(rid(id)) >= 2) {
                    	if(h(lid(lid(id))) >= h(lid(rid(id)))) 
                    		zag(id);
                    	else 
                    		zagzig(id);
					}
                } else {
                	if(lid(id)) id = lid(id);
                	else if(rid(id)) id = rid(id);
                	else id = 0;
				}
            }
            if(id) 
            	update(id);
            return;
		}
		int conduct_rank(int id,int v) {
			if(key(id) == v) 
				return size(lid(id))+1;
			else if(key(id) > v) 
				return conduct_rank(lid(id),v);
			else 
				return conduct_rank(rid(id),v)+size(lid(id))+cnt(id);
		}
		int conduct_number(int id,int k) {
			if(size(lid(id)) >= k) 
				return conduct_number(lid(id),k);
			else if(cnt(id)+size(lid(id)) >= k) 
				return key(id);
			else 
				return conduct_number(rid(id),k-size(lid(id))-cnt(id));
		}
		int conduct_pre(int v) {
			int id = ROOT;
			int pres = 0;
			while(id) {
				if(key(id) == v) {
					if(lid(id)) {
						id = lid(id);
						while(rid(id)) 
							id = rid(id);
						pres = id;
					}
					break;
				}
				if(key(id) < v&&(key(id) > key(pres)||key(pres) <= 0)) 
					pres = id;
				id = key(id) < v ? rid(id) : lid(id);
			}
			return key(pres);
		}
		int conduct_suc(int v) {
			int id = ROOT;
			int sucs = 0;
			while(id) {
				if(key(id) == v) {
					if(rid(id)) {
						id = rid(id);
						while(lid(id)) 
							id = lid(id);
						sucs = id;
					}
					break;
				}
				if(key(id) > v&&(key(id) < key(sucs)||key(sucs) <= 0)) 
					sucs = id;
				id = key(id) < v ? rid(id) : lid(id);
			}
			return key(sucs);
		}
	public : 
		void Init() {
			tot = 0, ROOT = 1;
			rid(ROOT) = lid(ROOT) = 0;
		}
		void Insert(int value) {
			if(tot == 0) {
				ROOT = newnode(value);
				return;
			}
			conduct_insert(ROOT,value);
		}
		void Delete(int value) {
			conduct_delete(ROOT,value);
		}
		int Rank(int value) {
			return conduct_rank(ROOT,value);
		}
		int Number(int position) {
			return conduct_number(ROOT,position);
		}
		int Pre(int value) {
			return conduct_pre(value);
		}
		int Suc(int value) {
			return conduct_suc(value);
		}
		void output(int id) {
			if(id == -1) return;
			printf("%d (%d %d) %d %d\n",id,lid(id),rid(id),key(id),cnt(id));
			output(lid(id));
			output(rid(id));
			printf("back to %d\n",id);
		}
		void Output() {
			output(ROOT);
			printf("\n");
		}
 } avl;
 void work_P3369() {
	avl.Init();
	int n;
	scanf("%d",&n);
	for(int i = 1, opt, x;i <= n;++i) {
		scanf("%d %d",&opt,&x);
		switch(opt) {
			case 1 : 
				avl.Insert(x);
				break;
			case 2 : 
				avl.Delete(x);
				break;
			case 3 : 
				printf("%d\n",avl.Rank(x));
				break;
			case 4 : 
				printf("%d\n",avl.Number(x));
				break;
			case 5 : 
				printf("%d\n",avl.Pre(x));
				break;
			case 6 : 
				printf("%d\n",avl.Suc(x));
				break;
		}
	}
}
signed main() {
	work_P3369();
}

\(\Large leafytree\)

点击查看代码
#include <stdio.h>
#include <stack>
#include <vector>
class LEAFY_TREE {
	private : 
		struct TREE {
			int lid, rid, pid;
			int gr, le, size;
		};
		std :: vector<TREE*> tree;
		std :: stack<int> RE_bin;
		#define lid(id) tree[id]->lid
		#define rid(id) tree[id]->rid
		#define pid(id) tree[id]->pid
		#define maxn(id) tree[id]->gr
		#define minn(id) tree[id]->le
		#define size(id) tree[id]->size
		#define sid(id,choice) (choice == 1 ? rid(id) : lid(id))
		double alpha = 0.29289321881345247559915563789515;
		double lim = 0.5857864376269049511983112757903;
		int ROOT, tot;
		int newnode(int v) {
			int id;
			if(!tot) {
				tree.push_back(new TREE);
				tree.push_back(new TREE);
			}
			if(RE_bin.empty()) {
				tree.push_back(new TREE);
				id = ++tot;
			} else {
				id = RE_bin.top();
				RE_bin.pop();
			}
			lid(id) = rid(id) = pid(id) = 0;
			maxn(id) = minn(id) = v;
			size(id) = 1;
			return id;
		}
		void delnode(int id) {
			RE_bin.push(id);
		}
		void update(int id) {
			if(lid(id)) {
				minn(id) = minn(lid(id));
				maxn(id) = maxn(rid(id));
				size(id) = size(lid(id))+size(rid(id));
			}
		}
		bool isRid(int id) {
			return id == rid(pid(id));
		}
		void rorate(int id) {
			int fp = pid(id), gp = pid(fp);
			int ch = isRid(id);
			sid(pid(sid(id,ch^1)) = fp,ch) = sid(id,ch^1);
			sid(pid(id) = gp,isRid(fp)) = id;
			sid(pid(fp) = id,ch^1) = fp;
			update(fp);
			update(id);
			if(fp == ROOT) 
				ROOT = id;
		}
		void maintain(int id) {
			int ch;
			if(lid(id)) {
				if(size(lid(id)) < size(id)*alpha) 
					ch = 1;
				else if(size(rid(id)) < size(id)*alpha) 
					ch = 0;
				else 
					return;
				if(size(sid(sid(id,ch),ch^1)) >= size(sid(id,ch))*lim) 
					rorate(sid(sid(id,ch),ch^1));
				rorate(sid(id,ch));
			}
		}
		void conduct_insert(int id,int v) {
			if(!ROOT) {
				ROOT = newnode(v);
				return;
			}
			if(size(id) == 1) {
				pid(lid(id) = newnode(v)) = id;
				pid(rid(id) = newnode(maxn(id))) = id;
				if(v > maxn(id)) 
					std :: swap(lid(id),rid(id));
			} else {
				conduct_insert(sid(id,v > maxn(lid(id))),v);
			}
			update(id);
			maintain(id);
		}
		void conduct_delete(int id,int v) {
			int ch = v > maxn(lid(id)), tmp;
			if(size(sid(id,ch)) == 1) {
				delnode(sid(id,ch));
				pid(tmp = sid(id,ch^1)) = pid(id);
				sid(pid(id),isRid(id)) = tmp;
				delnode(id);
				if(id == ROOT) 
					ROOT = tmp;
				id = tmp;
			} else {
				conduct_delete(sid(id,ch),v);
			}
			update(id);
			maintain(id);
		}
		int conduct_number(int id,int k) {
			if(size(id) == 1) 
				return id;
			else if(size(lid(id)) >= k) 
				return conduct_number(lid(id),k);
			else 
				return conduct_number(rid(id),k-size(lid(id)));
		}
		int conduct_rank(int id,int k) {
			if(k <= minn(id)) 
				return 0;
			else if(size(id) == 1) 	
				return 1;
			else if(maxn(lid(id)) >= k) 
				return conduct_rank(lid(id),k);
			else 
				return size(lid(id))+conduct_rank(rid(id),k);
		}
		int conduct_pre(int id,int v) {
			if(size(id) == 1) {
				return id;
			}
			else if(minn(rid(id)) >= v) 
				return conduct_pre(lid(id),v);
			else 
				return conduct_pre(rid(id),v);
		}
		int conduct_suc(int id,int v) {
			if(size(id) == 1) {
				return id;
			}
			else if(maxn(lid(id)) > v) 
				return conduct_suc(lid(id),v);
			else 
				return conduct_suc(rid(id),v);
		}
		#undef lid
		#undef rid
		#undef pid
		#undef sid
		#undef maxn
		#undef minn
		#undef size
	public : 
		void Insert(int v) {
			conduct_insert(ROOT,v);
		}
		void Delete(int v) {
			conduct_delete(ROOT,v);
		}
		int Rank(int k) {
			return conduct_rank(ROOT,k)+1;
		}
		int Number(int k) {
			return tree[conduct_number(ROOT,k)]->gr;
		}
		int Pre(int v) {
			return tree[conduct_pre(ROOT,v)]->gr;
		}
		int Suc(int v) {
			return tree[conduct_suc(ROOT,v)]->gr;
		}
} leafy;
void work_P3369() {
	int n;
	scanf("%d",&n);
	for(int i = 1, opt, x;i <= n;++i) {
		scanf("%d %d",&opt,&x);
		switch(opt) {
			case 1 : 
				leafy.Insert(x);
				break;
			case 2 : 
				leafy.Delete(x);
				break;
			case 3 : 
				printf("%d\n",leafy.Rank(x));
				break;
			case 4 : 
				printf("%d\n",leafy.Number(x));
				break;
			case 5 : 
				printf("%d\n",leafy.Pre(x));
				break;
			case 6 : 
				printf("%d\n",leafy.Suc(x));
				break;
		}
	}
}
signed main() {
	//std :: clog << "This is Leafy Tree." << std :: endl;
	work_P3369();
}

\(\Large B\ \text{树}\)

\(\Large Size\ Balanced\ Tree\)

一组样例
50
1 577793
1 408221
1 880861
2 408221
1 460353
1 223489
6 577713
4 2
5 889905
2 880861
1 100033
1 73956
1 22575
5 583761
6 571549
1 812645
4 3
1 643621
1 451623
6 14895
1 556691
4 1
1 225789
2 22575
1 632329
3 73956
1 316785
5 101413
4 11
5 639414
6 636353
1 272382
1 434049
2 643621
1 99617
2 577793
1 921581
1 894033
3 223489
1 767367
3 272382
1 642721
1 272033
3 632329
1 737721
1 864513
5 746457
1 877545
1 51097
1 484817
577793
460353
880861
577793
577793
100033
22575
22575
1
100033
643621
632329
643621
4
6
13
737721

https://blog.csdn.net/Acceptedxukai/article/details/6921334

@bikuhiku

posted @ 2022-06-03 10:58  bikuhiku  阅读(13)  评论(0编辑  收藏  举报