#include<cstdio>
//#define MAX 100001
#define MAX 10
//左偏树
struct Node
{
int key,dis;//key就是键值,dis是距离(一个节点到它的后代中,最近的外节点所经过的边数)
Node *left,*right;//左偏树是一个特殊的二叉树
//初始化,都是NULL
Node(int _key,int _dis,Node *null):key(_key),dis(_dis)
{
left=right=null;
}
}*null=new Node(-0x7fffffff,-1,NULL);//定义一个null,给null赋值
//交换左右子树
inline void SWAP(Node *&a,Node *&b)
{
Node *t=a; a=b; b=t;
}
//合并
Node* Merge(Node *a,Node *b)
{
//如果a的键值小于b的键值,把这两个树交换
if(a->key<b->key)
SWAP(a,b);
//如果b是空直接返回a树
if(b==null)
return a;
//这样就确定了a的键值大于b的键值,递归的合并。
a->right=Merge(a->right,b);
//如果a的左子树的距离小于a的右子树的距离,交换左右子树
if(a->left->dis<a->right->dis)
SWAP(a->left,a->right);
//将a的距离进行修改,返回a
a->dis=a->right->dis+1;
return a;
}
//插入,
inline void Insert(Node *&p,int x)
{
p=Merge(p,new Node(x,0,null));
}
//删除,
inline int Delete(Node *&p)
{
int ret=p->key;
Node* newroot=Merge(p->left,p->right);
delete p;
p=newroot;
return ret;
}
int n;
Node *root[MAX];
int set[MAX];
//查找根节点
int Find(int x)
{
if(set[x]==x) return x;
return set[x]=Find(set[x]);
}
//主函数
void work()
{
int m,a,b;
for(int i=1;i<=n;i++)
{
root[i]=null;
scanf("%d",&a);
Insert(root[i],a);
set[i]=i;//set应该是并查集
}
//输入冲突
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&a,&b);
int v1=Find(a),v2=Find(b);
//如果两个猴子认识的话
if(v1==v2)
printf("-1\n");
//如果两个猴子不认识
else
{
int t1=Delete(root[v1]),t2=Delete(root[v2]);
root[v1]=Merge(root[v1],root[v2]);
Insert(root[v1],t1>>1);
Insert(root[v1],t2>>1);
set[v2]=v1;
printf("%d\n",root[v1]->key);
}
}
}
int main()
{
freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
work();
}
return 0;
}
hdoj 1512 (左偏树)
最新推荐文章于 2017-07-14 12:02:45 发布