Treap方法,求调
查看原帖
Treap方法,求调
790641
easonlee2004楼主2024/4/24 13:38

样例点过了,测试点全挂,求调

使用treap来写的,key是二叉树,val是堆的权重。 我在初始化时候插入了-∞和∞两个节点,但是最后排名的时候有把排名减一或者加一。还是不知道哪里有问题。

#include<bits/stdc++.h>
using namespace std;

const int N=10010;
const int INF=2147483647;
int t,root,idx;

//heap为大根堆
struct node
{
	int l,r;
	int key,val; //bst的键值,heap的值
	int size;
}tr[N];

void pushup(int p) //更新父节点
{
	tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+1;
}

int get_node(int key) //获取新节点
{
	tr[++idx].key=key;
	tr[idx].val=rand();
	tr[idx].size=1;
	
	return idx;
}

void build() //创建正无穷负无穷节点
{
	get_node(-INF);
	get_node(INF);
	root=1,tr[root].r=2; //1为-INF,2为INF
}

void zig(int &p)
{
	int q=tr[p].l;
	tr[p].l=tr[q].r;
	tr[q].r=p;
	p=q;
	pushup(tr[p].r), pushup(p); 
}

void zag(int &p)
{
	int q=tr[p].r;
	tr[p].r=tr[q].l;
	tr[q].l=p;
	p=q;
	pushup(tr[p].l), pushup(p);
}

void insert(int &p,int key)
{
	if(!p) p=get_node(key);
	else if(tr[p].key>key)
	{
		insert(tr[p].l,key);
		if(tr[tr[p].l].val>tr[p].val) //左子树堆权值大于父节点,右旋
			zig(p);
	}
	else
	{
		insert(tr[p].r,key);
		if(tr[tr[p].r].val>tr[p].val) //右子树堆权值大于父节点,左旋
			zag(p);
	}
	pushup(p);
}

void remove(int &p,int key)
{
	if(!p) return;
	if(tr[p].key==key) //找到key
	{
		if(tr[p].l||tr[p].r)
		{
			if(!tr[p].r||tr[tr[p].l].val>tr[p].val) //右子树空或者左子树val>根节点
			{
				zig(p);
				remove(tr[p].r,key);
			}
			else //if(!tr[p].l||tr[tr[p].r].val>tr[p].val)
			{
				zag(p);
				remove(tr[p].l,key);
			}
		}
		else p=0;
	}
	
	else if(tr[p].key>key) //左右递归寻找key
		remove(tr[p].l,key);
	else
		remove(tr[p].r,key);

	pushup(p);
}

int get_rank(int &p,int key)
{
	if(!p) return 0;
	if(tr[p].key==key) return tr[tr[p].l].size+1;
	if(tr[p].key>key) return get_rank(tr[p].l,key); //左子树中的排名
	else return tr[tr[p].l].size+1+get_rank(tr[p].r,key); //左子树大小+p+右子树排名
}

int get_key(int &p,int rank)
{
	if(!p) return -INF;
	if(tr[tr[p].l].size>=rank) return get_key(tr[p].l,rank);
	if(rank==tr[tr[p].l].size+1) return tr[p].key;
	else return get_key(tr[p].r,rank-tr[tr[p].l].size-1);
}

int get_prev(int &p,int key)
{
	if(!p) return -INF;
	if(tr[p].key>=key) return get_prev(tr[p].l,key);
	else return max(tr[p].key,get_prev(tr[p].r,key));
}

int get_next(int &p,int key)
{
	if(!p) return INF;
	if(tr[p].key<=key) return get_next(tr[p].r,key);
	else return min(tr[p].key,get_next(tr[p].l,key));
}

int main()
{
	build();
	cin>>t;
	while(t--)
	{
		int op,x;
		cin>>op>>x;
		if(op==1) cout<<get_rank(root,x)-1<<endl;
		if(op==2) cout<<get_key(root,x+1)<<endl;
		if(op==3) cout<<get_prev(root,x)<<endl;
		if(op==4) cout<<get_next(root,x)<<endl;
		if(op==5) insert(root,x);
	}
	
	return 0;
}
2024/4/24 13:38
加载中...