zoukankan      html  css  js  c++  java
  • 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
    ");
                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;
    }
    心若向阳,无谓悲伤
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    牛客练习赛51 D题
    Educational Codeforces Round 72 (Rated for Div. 2) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Educational Codeforces Round 72 (Rated for Div. 2) B题
    Educational Codeforces Round 72 (Rated for Div. 2) A题
    《DSP using MATLAB》Problem 7.2
    《DSP using MATLAB》Problem 7.1
    《DSP using MATLAB》Problem 6.24
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6158297.html
Copyright © 2011-2022 走看看