Treap 模板

樹堆,在數據結構中也稱Treap,是指有一個隨機附加域滿足堆的性質的二叉搜索樹,其結構相當於以隨機數據插入的二叉搜索樹。其基本操作的期望時間複雜度爲O(logn)。相對於其他的平衡二叉搜索樹,Treap的特點是實現簡單,且能基本實現隨機平衡的結構。

採用結構體存儲節點

struct node
{
	int lc,rc;
	int pri;//rand();
	int key;
	int size;
	int cnt;//note the repeat
	#define lc(x) t[x].lc //left child
	#define rc(x) t[x].rc //right child
	#define v(x) t[x].key 
	#define p(x) t[x].pri
	#define c(x) t[x].cnt
	#define s(x) t[x].size
};

更新函數

inline void update(const int &k) 
{
	s(k)=s(lc(k))+s(rc(k))+c(k);
	return;
}

右旋

inline void Zig(int &k) //right turn;
{
	int y=lc(k);
	lc(k)=rc(y);
	rc(y)=k;
	s(y)=s(k);
	update(k);
	k=y;
	return;
}

左旋

inline void Zag(int &k) //left turn;
{
	int y=rc(k);
	rc(k)=lc(y);
	lc(y)=k;
	s(y)=s(k);
	update(k);
	k=y;
	return;
}

插入

inline void insert(int &k,const int &key)
{
	if(!k) {
		k=++pool;
		v(k)=key;
		p(k)=rand();
		c(k)=s(k)=1;
		lc(k)=rc(k)=0;
		return;
	}
	else ++s(k);
	if(v(k)==key) ++c(k);
	else if(key<v(k)) {
		insert(lc(k),key);
		if(p(lc(k))<p(k)) Zig(k); 
	}
	else {
		insert(rc(k),key);
		if(p(rc(k))<p(k)) Zag(k);
	}
	return;
}

刪除

inline void remove(int &k,const int &key)
{
	if(v(k)==key) {
		if(c(k)>1) --c(k),--s(k);//repeat numbers;
		else if(!lc(k)||!rc(k)) k=lc(k)+rc(k); //list node
		else if(p(lc(k))<p(rc(k))) Zig(k),remove(k,key);
		else Zag(k),remove(k,key);
		return;
	}
	--s(k); //maintenance size;
	if(key<v(k)) remove(lc(k),key);
	else remove(rc(k),key);
	return; 
}

求 x 的前趨(前趨定義爲小於 x,且最大的數);

inline int Query_pre(const int &key)
{
	int x=root,res=-INF;
	while(x) {
		if(v(x)<key) res=v(x),x=rc(x); //? <=
		else x=lc(x); 
	}
	return res;
}

求 x 的後繼(後繼定義爲大於 x,且最小的數)。

inline int Query_suf(const int &key) 
{
	int x=root,res=INF;
	while(x) {
		if(v(x)>key) res=v(x),x=lc(x); //??>=
		else x=rc(x);
	}
	return res;
}

查詢排名爲 x 的數;

inline int Query_kth(int k) 
{
	int x=root;
	while(x) {
		if(s(lc(x))<k&&s(lc(x))+c(x)>=k) return v(x);
		if(s(lc(x))>=k) x=lc(x);
		else k-=s(lc(x))+c(x),x=rc(x);
	}
	return 0;
}

查詢 x 數的排名(若有多個相同的數,因輸出最小的排名);

inline int Query_rank(const int &key)
{
	int x=root,res=0;
	while(x) {
		if(key==v(x)) return res+s(lc(x))+1;
		if(key<v(x)) x=lc(x);
		else res+=s(lc(x))+c(x),x=rc(x);
	}
	return res;
}

完整代碼

//普通平衡樹
#include<bits/stdc++.h>
#define INF 2147483646
using namespace std;
const int N=1e6+5;
struct node
{
	int lc,rc;
	int pri;//rand();
	int key;
	int size;
	int cnt;//note the repeat
	#define lc(x) t[x].lc //left child
	#define rc(x) t[x].rc //right child
	#define v(x) t[x].key 
	#define p(x) t[x].pri
	#define c(x) t[x].cnt
	#define s(x) t[x].size
};
node t[N];
int pool=0;
int root=0;
int n;
inline void update(const int &k) 
{
	s(k)=s(lc(k))+s(rc(k))+c(k);
	return;
}
inline void Zig(int &k) //right turn;
{
	int y=lc(k);
	lc(k)=rc(y);
	rc(y)=k;
	s(y)=s(k);
	update(k);
	k=y;
	return;
}
inline void Zag(int &k) //left turn;
{
	int y=rc(k);
	rc(k)=lc(y);
	lc(y)=k;
	s(y)=s(k);
	update(k);
	k=y;
	return;
}
inline void insert(int &k,const int &key)
{
	if(!k) {
		k=++pool;
		v(k)=key;
		p(k)=rand();
		c(k)=s(k)=1;
		lc(k)=rc(k)=0;
		return;
	}
	else ++s(k);
	if(v(k)==key) ++c(k);
	else if(key<v(k)) {
		insert(lc(k),key);
		if(p(lc(k))<p(k)) Zig(k); 
	}
	else {
		insert(rc(k),key);
		if(p(rc(k))<p(k)) Zag(k);
	}
	return;
}
inline void remove(int &k,const int &key)
{
	if(v(k)==key) {
		if(c(k)>1) --c(k),--s(k);//repeat numbers;
		else if(!lc(k)||!rc(k)) k=lc(k)+rc(k); //list node
		else if(p(lc(k))<p(rc(k))) Zig(k),remove(k,key);
		else Zag(k),remove(k,key);
		return;
	}
	--s(k); //maintenance size;
	if(key<v(k)) remove(lc(k),key);
	else remove(rc(k),key);
	return; 
}
inline int Query_pre(const int &key)
{
	int x=root,res=-INF;
	while(x) {
		if(v(x)<key) res=v(x),x=rc(x); //? <=
		else x=lc(x); 
	}
	return res;
}
inline int Query_suf(const int &key) 
{
	int x=root,res=INF;
	while(x) {
		if(v(x)>key) res=v(x),x=lc(x); //??>=
		else x=rc(x);
	}
	return res;
}
inline int Query_kth(int k) 
{
	int x=root;
	while(x) {
		if(s(lc(x))<k&&s(lc(x))+c(x)>=k) return v(x);
		if(s(lc(x))>=k) x=lc(x);
		else k-=s(lc(x))+c(x),x=rc(x);
	}
	return 0;
}
inline int Query_rank(const int &key)
{
	int x=root,res=0;
	while(x) {
		if(key==v(x)) return res+s(lc(x))+1;
		if(key<v(x)) x=lc(x);
		else res+=s(lc(x))+c(x),x=rc(x);
	}
	return res;
}
/*
1、插入 x 數;
2、刪除 x 數(若有多個相同的數,因只刪除一個);
3、查詢 x 數的排名(若有多個相同的數,因輸出最小的排名);
4、查詢排名爲 x 的數;
5、求 x 的前趨(前趨定義爲小於 x,且最大的數);
6、求 x 的後繼(後繼定義爲大於 x,且最小的數)。
*/
int main()
{
//	freopen("1.in","r",stdin);
	scanf("%d",&n);
	int opt,x;
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&opt,&x);
		switch(opt) {
			case 1 : insert(root,x); break;
			case 2 : remove(root,x); break;
			case 3 : printf("%d\n",Query_rank(x)); break;
			case 4 : printf("%d\n",Query_kth(x)); break;
			case 5 : printf("%d\n",Query_pre(x)); break;
			case 6 : printf("%d\n",Query_suf(x)); break; 
		}
	}
//	getchar();
	return 0;
}

注:代碼部分來自《一本通提高篇》
有所改動。

發佈了14 篇原創文章 · 獲贊 1 · 訪問量 1561
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章