hdoj 1512 (左偏树)

来源:互联网 发布:光年seo日志分析工具 编辑:程序博客网 时间:2024/05/29 19:46
#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;}

原创粉丝点击