POJ3481 Double Queue (Splay)

题意:给出三种操作,1表示加入一个值和一个优先级,2表示找到最大优先级的数的值并输出,然后去掉这个数,3表示找到最小优先级的值并输出然后去掉。。。

Splay的模板,写的时候除了一点问题,这里涉及到了插入和删除操作,插入按平衡二叉树的操作就差不多了,删除的时候先把要删除的移动到根节点,然后找第一个比根节点优先级小的数(如果没有直接删掉这个节点,把根节点右移下就好),然后把那个数旋转到根节点的左节点,然后删掉根节点,左节点接上原来的右子树就好了。。

如果找出空集就不删了,我是这样处理的。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=222222;
struct Node
{
	Node *ch[2];
	Node *pre;
	int val,pro;
}p[MAXN],nil;
int tot;
Node *null=&p[0];
Node *root=null;
void Rotate(Node *x,int c)
{
	Node *y=x->pre;
	y->ch[!c]=x->ch[c];
	if(x->ch[c]!=null)
	{
		x->ch[c]->pre=y;
	}
	x->pre=y->pre;
	if(y->pre->ch[0]==y)
	{
		y->pre->ch[0]=x;
	}
	else
		y->pre->ch[1]=x;
	y->pre=x;
	x->ch[c]=y;
	if(x!=root)
		root=x;
}
void splay(Node *x,Node *f)
{
	if(x==f)
		return;
	while(x->pre!=f)
	{
		if(x->pre->pre==f)
		{
			if(x->pre->ch[0]==x)
				Rotate(x,1);
			else
				Rotate(x,0);
		}
		else
		{
			Node *y=x->pre,*z=y->pre;
			if(z->ch[0]==y)
			{
				if(y->ch[0]==x)
					Rotate(y,1),Rotate(x,1);
				else
					Rotate(x,0),Rotate(x,1);
			}
			else
			{
				if(y->ch[1]==x)
					Rotate(y,0),Rotate(x,0);
				else
					Rotate(x,1),Rotate(x,0);
			}
		}
	}
}
Node *new_Node(int val,int pro)
{
	Node *rt=&p[++tot];
	rt->val=val;
	rt->pro=pro;
	rt->ch[0]=rt->ch[1]=rt->pre=null;
	return rt;
}
Node *insert(Node *rt,int val,int pro)
{
	if(rt==null)
	{
		rt=new_Node(val,pro);
		return rt;
	}
	if(rt->pro>pro)
	{
		if(rt->ch[0]!=null)
			rt->ch[0]=insert(rt->ch[0],val,pro);
		else
		{
			Node *rt1=new_Node(val,pro);
			rt1->pre=rt;
			rt->ch[0]=rt1;
		}
	}
	else
	{
		if(rt->ch[1]!=null)
			rt->ch[1]=insert(rt->ch[1],val,pro);
		else
		{
			Node *rt1=new_Node(val,pro);
			rt1->pre=rt;
			rt->ch[1]=rt1;
		}
	}
	return rt;
}
void Delete(Node *x)
{
	splay(x,null);
	if(x->ch[0]==null)
	{
		if(x->ch[1]==null)
			root=null;
		else
		{
			root=x->ch[1];
			x=x->ch[1];
			x->pre=null;
		}
	}
	else
	{
		Node *y=x->ch[0];
		while(y->ch[1]!=null)
			y=y->ch[1];
		splay(y,x);
		y->ch[1]=x->ch[1];
		if(x->ch[1]!=null)
			x->ch[1]->pre=y;
		y->pre=null;
		root=x=y;
	}
}
Node *querymx(Node *rt)
{
	if(rt==null)
		return null;
	if(rt->ch[1]!=null)
		return querymx(rt->ch[1]);
	else
		return rt;
}
Node *querymi(Node *rt)
{
	if(rt==null)
		return null;
	if(rt->ch[0]!=null)
		return querymi(rt->ch[0]);
	else
		return rt;
}
int main()
{
	int op,x,y;
	tot=0;
	Node *L;
	while(scanf("%d",&op)==1&&op)
	{
		if(op==1)
		{
			scanf("%d%d",&x,&y);
			root=insert(root,x,y);
			splay(root,null);
		}
		else if(op==2)
		{
			L=querymx(root);
			printf("%d\n",L->val);
			if(L!=null)
				Delete(L);
		}
		else 
		{
			L=querymi(root);
			printf("%d\n",L->val);
			if(L!=null)
				Delete(L);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值