HDU 4010.Query on The Trees 解题报告

题意:

  给出一颗树,有4种操作:

     1、如果x和y不在同一棵树上则在xy连边

     2、如果x和y在同一棵树上并且x!=y则把x换为树根并把y和y的父亲分离

     3、如果x和y在同一棵树上则x到y的路径上所有的点权值+w

     4、如果x和y在同一棵树上则输出x到y路径上的最大值

 

动态树入门题:

#include <iostream>
#include <cstdio>
using namespace std;

const int MAXN = 333333;

struct node {
    int val, max, inc;
    bool rev;
    node *par, *Ch[2];
} dt[MAXN], *NIL = dt;

struct LinkcutTree {
    inline void _inc (node * x,  int inc) {
        if (x == NIL) return;
        x->inc += inc, x->val += inc, x->max += inc;
    }
    inline void clear (node *const x) {
        if (x == NIL) return ;
        if (x->inc) {
            _inc (x->Ch[0], x->inc);
            _inc (x->Ch[1], x->inc);
            x->inc = 0;
        }
        if (x->rev) {
            swap (x->Ch[0], x->Ch[1]);
            x->Ch[0]->rev ^= 1;
            x->Ch[1]->rev ^= 1;
            x->rev = 0;
        }
    }
    inline void update (node * x) {
        clear (x);
        clear (x->Ch[0]), clear (x->Ch[1]);
        x->max = max (x->val, max (x->Ch[0]->max, x->Ch[1]->max) );
    }
    void Rotate (node *x) {
        node *p = x->par, *g = p->par;
        clear (p),clear (x);
        int c = p->Ch[0] == x; //0左旋,1右旋
        p->Ch[c ^ 1] = x->Ch[c];
        if (x->Ch[c] != NIL) x->Ch[c]->par = p;
        x->par = g;
        if (g->Ch[0] == p) g->Ch[0] = x; else
              if (g->Ch[1] == p) g->Ch[1] = x;
        x->Ch[c] = p;
        p->par = x;
        update (p);
    }
    void Splay (node *x) {
           if(x==NIL) return ;
        while (x->par != NIL && (x->par->Ch[0] == x || x->par->Ch[1] == x) ) {
            if (x->par != NIL)
                Rotate (x);
            else {
                node *p = x->par, *g = p->par;
                if ( (g->Ch[1] == p) == (p->Ch[1] == x) )
                    Rotate (p), Rotate (x);
                else
                    Rotate (x), Rotate (x);
            }
        }
        update (x);
    }
    node *Access (node *u) {
        node *v = NIL;
        for (; u != NIL; u = u->par) {
            Splay (u);
            u->Ch[1] = v;
            update (v = u);
        }
        return v;
    }
    node *getroot (node *x) {
        for (x = Access (x); clear (x), x->Ch[0] != NIL; x = x->Ch[0]);
        return x;
    }
    inline void evert (node *x) {
        Access (x)->rev ^= 1;
        Splay (x);
    }
    inline void link (node *x, node *y) {
        evert (x);
        x->par = y;
        Access (x);
    }
    inline void cut (node *x, node *y) {
        evert (x);
        Access (y);
        Splay (y);
        y->Ch[0]->par = NIL;
        y->Ch[0] = NIL;
        update (y);
    }
    inline int query (node *x, node *y) {
        evert (x);
        Access (y), Splay (y);
        return y->max;
    }
    inline void modify (node *x, node *y, int w) {
        evert (x);
        Access (y), Splay (y);
        _inc (y, w);
    }
} LCT;
int n, m;
int main() {
    while (scanf ("%d", &n) != EOF) {
        for (int i = 0; i <= n; i++) {
            dt[i].val = dt[i].max = dt[i].inc = 0;
            dt[i].par = dt[i].Ch[0] = dt[i].Ch[1] = NIL;
            dt[i].rev = 0;
        }
        for (int i = 1, x, y; i < n; ++i) {
            scanf ("%d %d", &x, &y);
            LCT.link (dt + x, dt + y);
        }
        for (int i = 1, x; i <= n; ++i) {
            scanf ("%d", &x);
            node *tem = dt + i;
            LCT.Splay (tem);
            tem->val = tem->max = x;
            LCT.update (tem);
        }
        scanf ("%d", &m);
        for (int i = 0, op, x, y, z; i < m; ++i) {
            scanf ("%d%d%d", &op, &x, &y);
            switch (op) {
            case 1:
                if (LCT.getroot (dt + x) == LCT.getroot (dt + y) ) printf ("-1\n");
                else LCT.link (dt + x, dt + y); break;
            case 2:
                if (x == y || LCT.getroot (dt + x) != LCT.getroot (dt + y) ) printf ("-1\n");
                else LCT.cut (dt + x, dt + y); break;
            case 3:
                scanf ("%d", &z);
                if (LCT.getroot (dt + y) != LCT.getroot (dt + z) ) printf ("-1\n");
                else LCT.modify (dt + y, dt + z, x); break;
            case 4:
                if (LCT.getroot (dt + x) != LCT.getroot (dt + y) ) printf ("-1\n");
                else printf ("%d\n", LCT.query (dt + x, dt + y) ); break;
            }
        }
        putchar (10);
    }
}
View Code

 

posted @ 2014-10-04 19:34  keambar  阅读(705)  评论(0编辑  收藏  举报