Loading

[题解]AT_abc222_f [ABC222F] Expensive Expense

板子题,模拟赛场切了。

思路

线段树换根板子题。

因为需要求每一个点的答案,所以定义 \(dp_i\) 表示以 \(i\) 为根的最长距离。

考虑将一个点 \(v\) 转化为根,树的形态会发生什么变化(假设 \(v\) 的父亲节点是 \(u\))。

发现在 \(v\) 子树中的节点,距离都会减少 \(w_{u \to v}\),其它节点都会加 \(w_{u \to v}\)。这个变化显然是可以将 DFS 序剖出来,然后用线段树优化的。

因为不能选择自己作为终点,所以查询最大值的时候避开即可。

Code

#include <bits/stdc++.h>
#define re register
#define int long long

using namespace std;

const int N = 2e5 + 10,M = 4e5 + 10;
int n;
int dp[N];
int idx,h[N],ne[M],e[M],w[M],p[N];
int num,f[N],d[N],sz[N],wson[N],id[N],tp[N];

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

inline void add(int a,int b,int c){
    ne[idx] = h[a];
    e[idx] = b;
    w[idx] = c;
    h[a] = idx++;
}

struct chain{
    #define ls(u) (u << 1)
    #define rs(u) (u << 1 | 1)

    struct node{
        int l,r;
        int Max,tag;
    }tr[N << 2];

    inline void calc(int u,int k){
        tr[u].Max += k;
        tr[u].tag += k;
    }

    inline void pushup(int u){
        tr[u].Max = max(tr[ls(u)].Max,tr[rs(u)].Max);
    }

    inline void pushdown(int u){
        if (tr[u].tag){
            calc(ls(u),tr[u].tag);
            calc(rs(u),tr[u].tag);
            tr[u].tag = 0;
        }
    }

    inline void build(int u,int l,int r){
        tr[u] = {l,r};
        if (l == r) return;
        int mid = l + r >> 1;
        build(ls(u),l,mid);
        build(rs(u),mid + 1,r);
        pushup(u);
    }

    inline void modify(int u,int l,int r,int k){
        if (l <= tr[u].l && tr[u].r <= r){
            calc(u,k);
            return;
        }
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(ls(u),l,r,k);
        if (r > mid) modify(rs(u),l,r,k);
        pushup(u);
    }

    inline int query(int u,int l,int r){
        if (l <= tr[u].l && tr[u].r <= r) return tr[u].Max;
        pushdown(u);
        int res = 0;
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) res = max(res,query(ls(u),l,r));
        if (r > mid) res = max(res,query(rs(u),l,r));
        return res;
    }

    inline void modify_node(int x,int k){
        modify(1,id[x],id[x],k);
    }

    inline void modify_tree(int x,int k){
        modify(1,id[x],id[x] + sz[x] - 1,k);
    }

    inline int query_sec(int l,int r){
        if (l > r) return 0;
        return query(1,l,r);
    }

    #undef ls
    #undef rs
}tree;

inline void dfs1(int u,int fa){
    sz[u] = 1;
    f[u] = fa;
    d[u] = d[fa] + 1;
    for (re int i = h[u];~i;i = ne[i]){
        int j = e[i];
        if (j == fa) continue;
        dfs1(j,u);
        if (sz[j] > sz[wson[u]]) wson[u] = j;
        sz[u] += sz[j];
    }
}

inline void dfs2(int u,int fa,int top){
    num++;
    id[u] = num;
    tp[u] = top;
    if (!wson[u]) return;
    dfs2(wson[u],u,top);
    for (re int i = h[u];~i;i = ne[i]){
        int j = e[i];
        if (j == fa || j == wson[u]) continue;
        dfs2(j,u,j);
    }
}

inline void dfs_val(int u,int fa,int d){
    tree.modify_node(u,d + p[u]);
    for (re int i = h[u];~i;i = ne[i]){
        int j = e[i];
        if (j == fa) continue;
        dfs_val(j,u,d + w[i]);
    }
}

inline void dfs_get(int u,int fa){
    for (re int i = h[u];~i;i = ne[i]){
        int j = e[i];
        if (j == fa) continue;
        tree.modify_tree(1,w[i]);
        tree.modify_tree(j,-2 * w[i]);
        dp[j] = max(tree.query_sec(1,id[j] - 1),tree.query_sec(id[j] + 1,n));
        dfs_get(j,u);
        tree.modify_tree(1,-w[i]);
        tree.modify_tree(j,2 * w[i]);
    }
}

signed main(){
    memset(h,-1,sizeof(h));
    n = read();
    for (re int i = 1;i < n;i++){
        int a,b,c;
        a = read();
        b = read();
        c = read();
        add(a,b,c);
        add(b,a,c);
    }
    for (re int i = 1;i <= n;i++) p[i] = read();
    dfs1(1,0);
    dfs2(1,0,1);
    tree.build(1,1,n);
    dfs_val(1,0,0);
    dp[1] = max(tree.query_sec(1,id[1] - 1),tree.query_sec(id[1] + 1,n));
    dfs_get(1,0);
    for (re int i = 1;i <= n;i++) printf("%lld\n",dp[i]);
    return 0;
}
posted @ 2023-11-04 14:03  BeautifulWish  阅读(10)  评论(0编辑  收藏  举报