首页 > 代码库 > hdu1512 Monkey King(并查集,左偏堆)

hdu1512 Monkey King(并查集,左偏堆)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1512

 

题目大意:有n个猴子,一开始每个猴子只认识自己。每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害。如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认识了,不打不相识嘛。现在给m组询问,如果2只猴子相互认识,输出-1,否则他们各自找自己认识的最牛叉的猴子单挑,求挑完后这拨猴子力量最大值。

 

 

技术分享
/*每次给出要争吵的猴子a和b,用并查集判断如果他们是朋友输出-1如果不是,找出a,b在的堆的根A,B,分别合并A,B的左右孩子,再合并一下。之后把A,B的数据更改一下:权值除以2,左右孩子设为0,再插入到堆中即可。最后输出堆顶。*/ #include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 100005;int m,n;int set[N];struct node{    int l,r,dis,key;}tree[N];int find(int x) {return set[x] == x ? x : set[x] = find(set[x]);}int merge(int a,int b){    if(!a)        return b;    if(!b)        return a;    if(tree[a].key < tree[b].key)//大堆        swap(a,b);    tree[a].r = merge(tree[a].r,b);    set[tree[a].r] = a;//并查    if(tree[tree[a].l].dis < tree[tree[a].r].dis)        swap(tree[a].l,tree[a].r);    if(tree[a].r)        tree[a].dis = tree[tree[a].r].dis + 1;    else        tree[a].dis = 0;    return a;}int pop(int a){    int l = tree[a].l;    int r = tree[a].r;    set[l] = l;//因为要暂时删掉根,所以左右子树先作为根    set[r] = r;    tree[a].l = tree[a].r = tree[a].dis = 0;    return merge(l,r);}int nextint(){    char c;    int ret = 0;    while((c = getchar()) > 9 || c < 0)        ;    ret = c - 0;    while((c = getchar()) >= 0 && c <= 9)        ret = ret * 10 + c - 0;    return ret;}void print(int a){    if(!a)        return;    print(a/10);    putchar(a%10 + 0);}int main(){    int a,b,i;    while(~scanf("%d",&n))    {        for(i = 1;i <= n;i ++)        {;            tree[i].key = nextint();            set[i] = i;            tree[i].l = tree[i].r = tree[i].dis = 0;        }        m = nextint();        while(m --)        {            a = nextint();            b = nextint();            int ra = find(a);            int rb = find(b);            if(ra == rb)                printf("-1\n");            else            {                int rra = pop(ra);//ra左右子树合并                tree[ra].key /= 2;                ra = merge(rra,ra);//重新插入ra 找到合适的位置                int rrb = pop(rb);                tree[rb].key /= 2;                rb = merge(rrb,rb);                print(tree[merge(ra,rb)].key);                putchar(10);            }        }    }    return 0;}
心若向阳,无谓悲伤

 

hdu1512 Monkey King(并查集,左偏堆)