HDU_1512

    这个题目用左偏树做的居多,昨天晚上突然想到其实用一棵splay也能方便的实现合并的操作,于是就用splay写了。

    在fight之前,要先找到两棵树中的最大值,然后splay到根部并修改。之后为了实现合并,可以将一棵splay“最右边”的元素splay到根部,这样根的右子树就为空了,直接把另一棵树放到这个位置即可。

#include<stdio.h>
#include<string.h>
#define MAXD 100010
#define INF 0x7fffffff
int N;
struct Splay
{
    int pre, ls, rs, key, max;
    void update(); void zig(int ); void zag(int ); void splay(int );
    void renew()
    {
        pre = ls = rs = 0;
    }
}sp[MAXD];
int Max(int x, int y)
{
    return x > y ? x : y;
}
void Splay::update()
{
    max = Max(Max(sp[ls].max, sp[rs].max), key);
}
void Splay::zig(int x)
{
    int y = rs, fa = pre;
    rs = sp[y].ls, sp[rs].pre = x;
    sp[y].ls = x, pre = y;
    sp[y].pre = fa, sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y;
    update();
}
void Splay::zag(int x)
{
    int y = ls, fa = pre;
    ls = sp[y].rs, sp[ls].pre = x;
    sp[y].rs = x, pre = y;
    sp[y].pre = fa, sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y;
    update();
}
void Splay::splay(int x)
{
    int y, z;
    for(; pre != 0;)
    {
        y = pre;
        if(sp[y].pre == 0)
            sp[y].rs == x ? sp[y].zig(y) : sp[y].zag(y);
        else
        {
            z = sp[y].pre;
            if(sp[z].rs == y)
            {
                if(sp[y].rs == x)
                    sp[z].zig(z), sp[y].zig(y);
                else
                    sp[y].zag(y), sp[z].zig(z);
            }
            else
            {
                if(sp[y].ls == x)
                    sp[z].zag(z), sp[y].zag(y);
                else
                    sp[y].zig(y), sp[z].zag(z);
            }
        }
    }
    update();
}
void init()
{
    int i;
    sp[0].max = -INF;
    for(i = 1; i <= N; i ++)
    {
        sp[i].renew();
        scanf("%d", &sp[i].key);
        sp[i].max = sp[i].key;
    }
}
int findmax(int cur, int v)
{
    if(sp[cur].key == v)
        return cur;
    if(sp[sp[cur].ls].max == v)
        return findmax(sp[cur].ls, v);
    else
        return findmax(sp[cur].rs, v);
}
int findlast(int cur)
{
    if(sp[cur].rs)
        return findlast(sp[cur].rs);
    else
        return cur;
}
int romax(int x)
{
    int t = findmax(x, sp[x].max);
    sp[t].splay(t);
    return t;
}
int rolast(int x)
{
    int t = findlast(x);
    sp[t].splay(t);
    return t;
}
int findroot(int x)
{
    for(; sp[x].pre != 0; x = sp[x].pre);
    return x;
}
void fight(int x, int y)
{
    int tx, ty, t;
    tx = findroot(x), ty = findroot(y);
    if(tx == ty)
        printf("-1\n");
    else
    {
        tx = romax(tx), ty = romax(ty);
        sp[tx].key /= 2, sp[tx].update();
        sp[ty].key /= 2, sp[ty].update();
        t = rolast(tx);
        sp[t].rs = ty, sp[ty].pre = t;
        sp[t].update();
        printf("%d\n", sp[t].max);
    }
}
void solve()
{
    int i, x, y, m;
    scanf("%d", &m);
    for(i = 0; i < m; i ++)
    {
        scanf("%d%d", &x, &y);
        fight(x, y);
    }
}
int main()
{
    while(scanf("%d", &N) == 1)
    {
        init();
        solve();
    }
    return 0;
}
posted on 2012-06-17 11:34  Staginner  阅读(365)  评论(0编辑  收藏  举报