HDU 5692 Snacks

题目链接【http://acm.hdu.edu.cn/showproblem.php?pid=5692】

题意:一棵树,每个节点有权值,有两种操作:1、修改某个点的权值,2、求以x根的子树中的节点到根的权值和的最大值。

题解:DFS序:对点进行重新编号,每个子树中的所有的节点的编号是连续的。映射到线段树上,进行区间修改,区间查询。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 15;
int T, N, Q;
LL a[maxn], sum[maxn];
struct Edge
{
    int to, next;
    Edge (int to = 0, int next = 0): to(to), next(next) {}
} E[maxn * 2];
int head[maxn], tot;
void initEdge()
{
    for(int i = 0; i <= N + 15; i++) head[i] = -1;
    tot = 0;
}
void addEdge(int u, int v)
{
    E[tot] = Edge(v, head[u]);
    head[u] = tot++;
}
int L[maxn], R[maxn], dfs_clock;
void DFS(int u, int fa)
{
    L[u] = ++dfs_clock;
    sum[L[u]] = a[u] + sum[L[fa]];
    for(int k = head[u]; ~k; k = E[k].next)
    {
        int v = E[k].to;
        if(v == fa) continue;
        DFS(v, u);
    }
    R[u] = dfs_clock;
}
LL ma[maxn * 4], fg[maxn * 4];
void Build(int id, int L, int R)
{
    fg[id] = 0;
    if(L == R)
    {
        ma[id] = sum[L];
        return ;
    }
    int mid = (L + R) >> 1;
    Build(id << 1, L, mid);
    Build(id << 1 | 1, mid + 1, R);
    ma[id] = max(ma[id << 1], ma[id << 1 | 1]);
}
inline void push_down(int id)
{
    if(fg[id])
    {
        fg[id << 1] += fg[id];
        ma[id << 1] += fg[id];
        fg[id << 1 | 1] += fg[id];
        ma[id << 1 | 1] += fg[id];
        fg[id] = 0;
    }
}
void update(int id, int L, int R, int l, int r, LL val)
{
    if(L == l && R == r)
    {
        fg[id] += val;
        ma[id] += val;
        return ;
    }
    push_down(id);
    int mid = (L + R) >> 1;
    if(r <= mid)
        update(id << 1, L, mid, l, r, val);
    else if(l >= mid + 1)
        update(id << 1 | 1, mid + 1, R, l, r, val);
    else
    {
        update(id << 1, L, mid, l, mid, val);
        update(id << 1 | 1, mid + 1, R, mid + 1, r, val);
    }
    ma[id] = max(ma[id << 1], ma[id << 1 | 1]);
}
LL query(int id, int L, int R, int l, int r)
{
    if(L == l && R == r)
        return ma[id];
    push_down(id);
    int mid = (L + R) >> 1;
    if(r <= mid)
        return query(id << 1, L, mid, l, r);
    else if(l >= mid + 1)
        return query(id << 1 | 1, mid + 1, R, l, r);
    else
    {
        LL t = query(id << 1, L, mid, l, mid);
        return max(t, query(id << 1 | 1, mid + 1, R, mid + 1, r));
    }
}
int main ()
{
    int ic = 0;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d", &N, &Q);
        initEdge();
        for(int i = 1; i <= N - 1; i++)
        {
            int u, v;
            scanf("%d %d", &u, &v);
            addEdge(u + 1, v + 1);
            addEdge(v + 1, u + 1);
        }
        for(int i = 1; i <= N; i++) scanf("%lld", &a[i]);
        dfs_clock = 0, DFS(1, 0);
        Build(1, 1, N);
        printf("Case #%d:\n", ++ic);
        for(int i = 1; i <= Q; i++)
        {
            int ty, x;
            LL y;
            scanf("%d", &ty);
            if(ty == 0)
            {
                scanf("%d %lld", &x, &y);
                x++;
                update(1, 1, N, L[x], R[x], y - a[x]);
                a[x] = y;
            }
            else if(ty == 1)
            {
                scanf("%d", &x);
                x++;
                LL ans = query(1, 1, N, L[x], R[x]);
                printf("%lld\n", ans);
            }
        }
    }
    return 0;
}

 

posted @ 2017-08-07 20:56  _Mickey  阅读(150)  评论(0编辑  收藏  举报