HDU5692 Snacks(dfs序 + 线段树)

传送门: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) >> 1
const 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值