POJ 2763 Housewife Wind

POJ_2763

    用link-cut-tree或者树链剖分都可以,只要支持单点修改和区间求和就可以了。但后面看dicuss里面说是树状数组和LCA,但由于这两个东西我暂时都没研究过,所以就没再深究这种解法了。

#include<stdio.h>
#include<string.h>
#define MAXD 100010
#define MAXM 200010
int N, Q, S, first[MAXD], e, next[MAXM], v[MAXM], w[MAXM], q[MAXD], dep[MAXD];
struct Edge
{
    int x, y, z;
}edge[MAXD];
struct Splay
{
    int pre, ls, rs, sum, key;
    bool root;
    void update(); void zig(int ); void zag(int ); void splay(int );
    void renew()
    {
        root = true;
        pre = ls = rs = 0;
    }
}sp[MAXD];
void Splay::update()
{
    sum = sp[ls].sum + sp[rs].sum + 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;
    if(root)
        root = false, sp[y].root = true;
    else
        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;
    if(root)
        root = false, sp[y].root = true;
    else
        sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y;
    update();
}
void Splay::splay(int x)
{
    int y, z;
    for(; !root;)
    {
        y = pre;
        if(sp[y].root)
            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 Swap(int &x, int &y)
{
    int t;
    t = x, x = y, y = t;
}
void prepare()
{
    int i, j, x, rear = 0;
    sp[0].sum = 0;
    q[rear ++] = 1;
    sp[1].renew(), dep[1] = 1;
    for(i = 0; i < rear; i ++)
    {
        x = q[i];
        for(j = first[x]; j != -1; j = next[j])
            if(v[j] != sp[x].pre)
            {
                sp[v[j]].renew(), sp[v[j]].pre = x, sp[v[j]].key = sp[v[j]].sum = w[j], dep[v[j]] = dep[x] + 1;
                q[rear ++] = v[j];
            }
    }
}
void add(int x, int y, int z)
{
    v[e] = y, w[e] = z;
    next[e] = first[x], first[x] = e ++;
}
void init()
{
    int i;
    memset(first, -1, sizeof(first));
    e = 0;
    for(i = 1; i < N; i ++)
    {
        scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].z);
        add(edge[i].x, edge[i].y, edge[i].z), add(edge[i].y, edge[i].x, edge[i].z);
    }
    prepare();
    for(i = 1; i < N; i ++)
        if(dep[edge[i].x] > dep[edge[i].y])
            Swap(edge[i].x, edge[i].y);
}
void access(int x)
{
    int fx;
    for(fx = x, x = 0; fx != 0; x = fx, fx = sp[x].pre)
    {
        sp[fx].splay(fx);
        sp[sp[fx].rs].root = true;
        sp[fx].rs = x, sp[x].root = false;
        sp[fx].update();
    }
}
void Query(int x)
{
    int fx;
    access(S);
    S = x;
    for(fx = x, x = 0; fx != 0; x = fx, fx = sp[x].pre)
    {
        sp[fx].splay(fx);
        if(sp[fx].pre == 0)
            printf("%d\n", sp[sp[fx].rs].sum + sp[x].sum);
        sp[sp[fx].rs].root = true;
        sp[fx].rs = x, sp[x].root = false;
        sp[fx].update();
    }
}
void Change(int x, int v)
{
    sp[x].splay(x);
    sp[x].key = v;
    sp[x].update();
}
void solve()
{
    int i, x, y, op;
    for(i = 0; i < Q; i ++)
    {
        scanf("%d%d", &op, &x);
        if(op == 0)
            Query(x);
        else
        {
            scanf("%d", &y);
            Change(edge[x].y, y);
        }
    }
}
int main()
{
    while(scanf("%d%d%d", &N, &Q, &S) == 3)
    {
        init();
        solve();
    }
    return 0;
}

你可能感兴趣的:(poj)