hdu 1512 Monkey King 左偏树

有这么一群猴子,他们喜欢打架,要是两个猴子没打过就会开打,打完后自己的val值减半,然后他们就变成好基友,他们之前各自的好基友

也变成了好基友,当两只猴子决斗时,并不一定是他们打,而是他们各自的好基友里面val值最大的出来打,如果他们本来就是好基友

那么就不打了,output  -1,否则output 打完后最大的val值:

利用左偏树求解,读入数据时为每一个猴子建立一颗左偏树,当两个猴子打架时,分别弹出root,然后打完,val减半,再将两个root和

剩下的左偏树进行合并:

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 1111111
#define typec int         // type of key val

using namespace std;
const int na = -1;
int swap(int &x,int &y)
{
    int t = x;
    x = y;
    y = t;
}
struct node
{
    typec key;
    int l, r, f, dist,id;
} tr[N];
int iroot(int i)                // find i's root
{
    if (i == na) return i;
    while (tr[i].f != na) i = tr[i].f;
    return i;
}
int merge(int rx, int ry)
{
    // two root: rx, ry
    if (rx == na) return ry;
    if (ry == na) return rx;
    if (tr[rx].key < tr[ry].key)
        swap(rx, ry);
    int r = merge(tr[rx].r, ry);
    tr[rx].r = r;
    tr[r].f = rx;
    if (tr[r].dist > tr[tr[rx].l].dist)
        swap(tr[rx].l, tr[rx].r);
    if (tr[rx].r == na) tr[rx].dist = 0;
    else tr[rx].dist = tr[tr[rx].r].dist + 1;
    return rx;                // return new root
}
int ins(int i, typec key, int root)
{
    // add a new node(i, key)
    tr[i].key = key;
    tr[i].l = tr[i].r = tr[i].f = na;
    tr[i].dist = 0;
    return root = merge(root, i);  // return new root
}
int del(int i)
{
    // delete node i
    if (i == na) return i;
    int x, y, l, r;
    l = tr[i].l;
    r = tr[i].r;
    y = tr[i].f;
    tr[i].l = tr[i].r = tr[i].f = na;
    tr[x = merge(l, r)].f = y;
    if (y != na && tr[y].l == i)
        tr[y].l = x;
    if (y != na && tr[y].r == i)
        tr[y].r = x;
    for ( ; y != na; x = y, y = tr[y].f)
    {
        if (tr[tr[y].l].dist < tr[tr[y].r].dist)
            swap(tr[y].l, tr[y].r);
        if (tr[tr[y].r].dist + 1 == tr[y].dist) break;
        tr[y].dist = tr[tr[y].r].dist + 1;
    }
    if (x != na)
        return iroot(x); // return new root
    else return iroot(y);
}
node top(int root)
{
    return tr[root];
}
node pop(int &root)
{
    node out = tr[root];
    int l = tr[root].l, r = tr[root].r;
    tr[root].l = tr[root].r = tr[root].f = na;
    tr[l].f = tr[r].f = na;
    root = merge(l, r);
    return out;
}
int add(int i, typec val)  // tr[i].key += val
{
    if (i == na) return i;
    if (tr[i].l == na && tr[i].r == na && tr[i].f == na)
    {
        tr[i].key += val;
        return i;
    }
    typec key = tr[i].key + val;
    int rt = del(i);
    return ins(i, key, rt);
}
int init(int n)
{
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &tr[i].key); //%d: type of key
        tr[i].l = tr[i].r = tr[i].f = na;
        tr[i].dist = 0;
        tr[i].id=i;
    }

}
int main()
{
    int root = -1;
    int a1,a2,a3,root1,root2;
    int m,n,i;
    while(scanf("%d",&n)==1)
    {
        init(n);
        scanf("%d",&m);
        for(i=0; i<m; i++)
        {
            scanf("%d%d",&a1,&a2);
            root1=iroot(a1);
            root2=iroot(a2);
            if(root1==root2)
            {
                printf("-1\n");
                continue;
            }
            else
            {
                node top1,top2;
                top1=pop(root1);
                top2=pop(root2);
                tr[top1.id].key/=2;
                tr[top2.id].key/=2;
                top1.l = top1.r = top1.f = na;
                top1.dist = 0;

                top2.l = top2.r = top2.f = na;
                top2.dist = 0;
                root1=merge(root1,top1.id);
                root1=merge(root1,top2.id);
                root1=merge(root1,root2);
                top1=top(root1);
                printf("%d\n",top1.key);
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值