HDU5692 Snacks(dfs序 + 线段树)

来源:互联网 发布:无法触碰 知乎 编辑:程序博客网 时间:2024/04/29 18:37

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5692
两场百度之星打的十分郁闷,但是也发现了我还是有很多的知识不能灵活运用,比如这题,dfs序我是懂的,线段树也是懂的,但是就是不知道怎么来做这题。
       赛后看了takio菊苣的代码,觉得代码风格非常的清晰,很多地方加了空格以后看起来确实清楚很多。准备学习一下,虽然很影响手速,但是也慢慢改一改吧。
       这题的思路实际上是这样的。先通过一次dfs来求得很多信息,比如dfs序,距离0点的距离,线段树中的下标代表的点。然后把距离0点的距离做成一棵线段树,这样的话,在x的子树的序列中,[L[x], R[x]]这段区间内,一定有0点到某个最远的点的距离,如果求出这个区间内的最大值,那么就是题目要求的最大距离。我们考虑修改操作,如果修改一个点的值的话,其实就是相当于修改整个子树的值,那么就用一个区间修改操作直接修改整个区间的值就好了。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <iostream>#include <vector>#include <map>#include <set>#include <queue>#include <ctime>using namespace std;typedef long long ll;typedef pair<int,int> pii;#define pb push_back#define ls l, m#define rs m + 1, r#define lson l, m, rt << 1#define rson m + 1, r, rt << 1|1#define calm (l + r) >> 1const ll INF = 1e15;const int maxn = 100010;struct EE {    int to, next;    EE(){}    EE(int to, int next):to(to), next(next){}}edge[maxn << 1];struct node {    ll mx, tag;}tree[maxn << 2];int n, m, Case, Ecnt, tot;int head[maxn], L[maxn], R[maxn], rev[maxn];ll a[maxn], val[maxn];inline void add (int from, int to) {    edge[Ecnt] = EE(to, head[from]);    head[from] = Ecnt++;}void dfs (int s, int pre) {    val[s] += val[pre]; L[s] = ++tot; rev[tot] = s;    for (int i = head[s]; ~i; i = edge[i].next) {        int t = edge[i].to;        if (t == pre) continue;        dfs (t, s);    }    R[s] = tot;}inline void pushup (int rt) {    tree[rt].mx = max (tree[rt << 1].mx, tree[rt << 1 | 1].mx);}inline void pushdown (int rt) {    if (tree[rt].tag) {        tree[rt << 1].mx += tree[rt].tag;        tree[rt << 1 | 1].mx += tree[rt].tag;        tree[rt << 1].tag += tree[rt].tag;        tree[rt << 1 | 1].tag += tree[rt].tag;        tree[rt].tag = 0;    }}void build (int l, int r, int rt) {    tree[rt].tag = 0;    if (l == r) {        tree[rt].mx = val[rev[l]];        return;    }    int m = calm;    build (lson); build (rson);    pushup (rt);}void update (int L, int R, int c, int l, int r, int rt) {    if (L <= l && r <= R) {        tree[rt].mx += c;        tree[rt].tag += c;        return;    }    pushdown (rt);    int m = calm;    if (L <= m) update (L, R, c, lson);    if (R > m) update (L, R, c, rson);    pushup (rt);}ll query (int L, int R, int l, int r, int rt) {    if (L <= l && r <= R) {        return tree[rt].mx;    }    pushdown (rt);    int m = calm;    ll ans = -INF;//INF要设的大一点    if (L <= m) ans = query (L, R, lson);    if (R > m) ans = max (ans, query (L, R, rson));    return ans;}int main() {//    freopen ("D://input.txt", "r", stdin);    int T; scanf ("%d", &T);    while (T--) {        printf ("Case #%d:\n", ++Case);        scanf ("%d%d", &n, &m);        memset (head, -1, sizeof head); Ecnt = 0;        for (int i = 1; i < n; i++) {            int x, y; scanf ("%d%d", &x, &y);            ++x; ++y;            add (x, y); add (y, x);        }        for (int i = 1; i <= n; i++) {            scanf ("%I64d", &a[i]);            val[i] = a[i];        }        tot = 0; dfs (1, 0);        build (1, n, 1);        while (m--) {            int op, x; scanf ("%d%d", &op, &x); ++x;            if(!op) {                int y; scanf ("%d", &y);                update (L[x], R[x], y - a[x], 1, n, 1);                a[x] = y;            }            else {                printf ("%I64d\n", query (L[x], R[x], 1, n, 1));            }        }    }    return 0;}
0 0
原创粉丝点击