ZOJ 2334 HDU 1512 Monkey King

题意:

猴子们打架  认识的猴子不会打架  两仅仅猴子打完以后就认识了  A认识B B认识C A也认识C  每次打架由两伙猴子进行  分别选出自己的最高战斗力  在战斗之后两仅仅猴子战斗力减半  给出m次打架  输出打架后这一伙猴子里的最强战斗力


思路:

推断两仅仅猴子是不是一伙的  用到并查集

高速找出一伙猴子中的最强战斗力用到堆  但打完架两伙猴子合并时堆须要nlogn复杂度  因此用左偏树取代堆


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010

int n,m,tot;
int fa[N];
struct node
{
    int v,l,r,dis;
}nd[N];

int getf(int x)
{
    if(x!=fa[x]) fa[x]=getf(fa[x]);
    return fa[x];
}

int newnode(int x)
{
    nd[tot].v=x;
    nd[tot].l=0;
    nd[tot].r=0;
    nd[tot].dis=0;
    tot++;
    return tot-1;
}

int merge(int x,int y)
{
    if(!x) return y;
    if(!y) return x;
    if(nd[x].v<nd[y].v) swap(x,y);
    nd[x].r=merge(nd[x].r,y);
    if(nd[nd[x].l].dis<nd[nd[x].r].dis) swap(nd[x].l,nd[x].r);
    nd[x].dis=nd[nd[x].r].dis+1;
    return x;
}

int pop(int x)
{
    int tmp=merge(nd[x].l,nd[x].r);
    nd[x].dis=nd[x].l=nd[x].r=0;
    return tmp;
}

int main()
{
    int i,j,fi,fj,x;
    while(~scanf("%d",&n))
    {
        tot=1;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&j);
            fa[i]=newnode(j);
        }
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&i,&j);
            fi=getf(i);
            fj=getf(j);
            if(fi==fj) puts("-1");
            else
            {
                i=pop(fi);
                nd[fi].v/=2;
                j=pop(fj);
                nd[fj].v/=2;
                i=merge(i,j);
                i=merge(i,fi);
                i=merge(i,fj);
                fa[i]=fa[fi]=fa[fj]=i;
                printf("%d
",nd[i].v);
            }
        }
    }
    return 0;
}


原文地址:https://www.cnblogs.com/gcczhongduan/p/4478708.html