fhq treap 范浩强平衡树

https://www.luogu.com.cn/problem/P3369

随机大法好啊啊啊

插入数字的时候,把平衡树按x分裂,插入x后再合并,具体可以看代码

 

#include<iostream>
#include<algorithm> 
#include<cstdio>
#include<ctime>
#include<stack>
using namespace std;
const int maxn = 2e6+10;
struct Node{
	int l,r;
	int val,key;
	int siz;
}tree[maxn];

int l,r,cnt,p,x,n;



void update(int node){
	tree[node].siz = tree[tree[node].l].siz + tree[tree[node].r].siz + 1;
}


void split(int node,int x,int& l,int& r){//node分裂成l和r,l--val<= x   r--val > x     
	if(node == 0){
		l = r = 0;
		return ;
	}
	if(tree[node].val <= x){//左边部分 
		l = node;
		//左边儿子改了,继续分右边
		split(tree[node].r,x,tree[node].r,r); 
	}
	else{
		r = node;
		split(tree[node].l,x,l,tree[node].l); 
	}
	update(node);
}



int add(int val){
	cnt++;
	tree[cnt].siz = 1;
	tree[cnt].l = tree[cnt].r = 0;
	tree[cnt].val = val;
	tree[cnt].key = rand();
	
}




int merge(int l,int r){
	if(!l || !r) return l + r;//总有一个是叶子
	
	if(tree[l].key <= tree[r].key){//l做父亲 ,r比l大,所以r接上l的右子树 
		tree[l].r = merge(tree[l].r,r);
		update(l);
		return l; 
	} 
	else{
		tree[r].l = merge(l,tree[r].l);
		update(r);
		return r;
	}
}


int kth(int node,int k){//排名第k的数字 
	if(k <= tree[tree[node].l].siz){
		return kth(tree[node].l,k);
	} 
	else if(tree[tree[node].l].siz + 1 == k){
		return node;
	}
	else{
		k -= tree[tree[node].l].siz + 1;
		return kth(tree[node].r,k);
	}
}

//int kth(int u,int k)
//{//求排名第k的数
//	if(k<=tree[tree[u].l].siz)//在左区间 
//		return kth(tree[u].l,k);
//	else if(k==tree[tree[u].l].siz+1)//这个数为此区间的根 
//			return u;
//	else
//	{
//		k-=(tree[tree[u].l].siz+1);//排名为k要减少左儿子的节点数 
//		return kth(tree[u].r,k);//在右区间 
//	}
//}




int main(){
	int n;
	scanf("%d",&n);
	int root = 0;
	int p;
	
	srand((unsigned)time(NULL));
	
	while(n--){
		int op,x;
		scanf("%d %d",&op,&x);
		if(op == 1){
			split(root,x,l,r);// node分裂成l和r,l--val<= x   r--val > x     
			add(x);
			root = merge(merge(l,cnt),r); 
		}
		else if(op == 2){//删除x 
			split(root,x,l,r);
			split(l,x-1,l,p);
			
			p = merge(tree[p].l,tree[p].r);//可能有多个x 
			root = merge(merge(l,p),r);
		}
		else if(op == 3){//查询x的排名 
			split(root,x-1,l,r);
			printf("%d\n",tree[l].siz+1);//小于x的个数 
			root = merge(l,r);
		}
		else if(op == 4){//排名为x的数,记录重复 
			printf("%d\n",tree[kth(root,x)].val); 
		}
		else if(op == 5){
			split(root,x-1,l,r);
			
			printf("%d\n",tree[kth(l,tree[l].siz)].val);
			root = merge(l,r);
		}
		else{
			split(root,x,l,r);
			
			printf("%d\n",tree[kth(r,1)].val);
			
			root = merge(l,r);
		}
	}
	return 0;
	
}

  

上一篇:FFT/NTT字符串模糊匹配


下一篇:免费下载!《Apache RocketMQ 源码解析》带你深入了解Apache RocketMQ