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);
    }
}

时间: 2024-10-17 06:10:43

HDU 4010.Query on The Trees 解题报告的相关文章

HDU 4010 Query on The Trees (动态树)(Link-Cut-Tree)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意; 先给你一棵树,有 \(4\) 种操作: 1.如果 \(x\) 和 \(y\) 不在同一棵树上则在\(x-y\)连边. 2.如果 \(x\) 和 \(y\) 在同一棵树上并且 \(x!=y\) 则把 \(x\) 换为树根并把 \(y\) 和 \(y\) 的父亲分离. 3.如果 \(x\) 和 \(y\) 在同一棵树上则 \(x\) 到 \(y\) 的路径上所有的点权值\(+w\). 4

HDU 4010 Query on The Trees(动态树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意:一棵树,四种操作: (1)若x和y不在一棵树上,将x和y连边: (2)若x和y在一棵树上,将x变成树根,将y从x树上分离: (3)若x和y在一棵树上,将x到y路径上的所有值增加det: (4)若x和y在一棵树上,输出x到y路径上的最大值. 思路:1操作用link维护,2操作用cut,34操作先split(x,y),然后对y做tag,并且记录路径的max值. 1 #include<iost

hdu 4010 Query on The Trees(动态树)

题意:给定一幅图的连接情况,给出每个点的权值,四种操作: 1 x y 连接x.y所在子树: 2 x y 将同一棵树上的x,y分离,形成两棵子树: 3 w x y 将x.y之间路径上的所有点权加w: 4 x y 查询x.y路径上点权的最大值: 动态树学习参考:http://www.cnblogs.com/BLADEVIL/p/3510997.html http://wenku.baidu.com/view/75906f160b4e767f5acfcedb http://m.blog.csdn.ne

HDU 4010 Query on The Trees

题意: 一棵树  支持合并.分离.路径加权值.路径权值最大值 思路: LCT入门题  也是我的第一道-  代码来源于kuangbin巨巨  我只是整理出自己的风格留作模版- LCT比较好的入门资料是--<QTREE解法的一些研究> LCT基本做法就是先dfs建树  然后根据输入做上述4个操作 对于合并  就是把u转到树根  然后接在v上 对于分离  就是把u转到splay的根  然后切断与左子树的连接 对于路径加值  就是求出lca  然后包含u和v的子树以及lca点进行加值 对于路径求最值 

hdu 4010 Query on the trees LCT

维护一个带点权的无向图森林,支持: 1.删边 2.加边 3.增加某条链所有点的点权 4.求某条链上点权的最大值 大概思路: 前两个需要更改根(即需要翻转标记) 第三个又需要一个标记,第四个每个节点记录该splay中以该节点为根的子树的最大点权. 收获: 1.对于splay前的标记下传可用递归写法, 虽然慢一点,但不容易写错. 2.access的过程中,在边转换完成后要更新节点信息. 3.对于寻找某子树的根,可以一直向上(会途径重边和轻边)找,这样比access+splay快很多,也很好写. 4.

hdu 2066 一个人的旅行 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2066 题目意思:给出T条路,和草儿家相邻的城市编号,以及草儿想去的地方的编号.问从草儿家到达草儿想去的地方的最短时间是多少. 一开始自己写的只能处理单边出发的情况,对于以下这幅图,只能处理箭头所示的方向,不能向下,于是不知道为什么出现了百年难得一遇的Runtime Error(ACCESS_VIOLATION)! 10 2 31 3 53 8 42 5 25 8 31 4 74 9 129 10 2

hdu 2680 Choose the best route 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2680 题目意思:实质就是给定一个多源点到单一终点的最短路. 卑鄙题---有向图.初始化map时 千万不要写成 map[i][j] = map[j][i] = X. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespac

HDOJ 4010 Query on The Trees LCT

LCT: 分割.合并子树,路径上全部点的点权添加一个值,查询路径上点权的最大值 Query on The Trees Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 2582    Accepted Submission(s): 1208 Problem Description We have met so many problems

HDOJ 题目4010 Query on The Trees(Link Cut Tree连接,删边,路径点权加,路径点权最大值)

Query on The Trees Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 3602    Accepted Submission(s): 1587 Problem Description We have met so many problems on the tree, so today we will have a qu