zoukankan      html  css  js  c++  java
  • noip模拟赛 蒜头君的树

    分析:这道题问的是树上整体的答案,当然要从整体上去考虑.

          一条边对答案的贡献是这条边一端连接的点的个数*另一端连接的点的个数*边权,可以用一次dfs来统计答案,之后每次更改操作在原答案的基础上增减就好了.

    千万不要傻傻地去求LCA......事实证明只有10分.问的是任意两点最短距离之和,树上两个点的最短路径只有一条,所以才要去考虑每条边的贡献的.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 100010;
    
    long long n, head[maxn], nextt[maxn * 2], tot = 1, to[maxn * 2], w[maxn * 2], num[maxn], fa[maxn], d[maxn], m;
    long long ans;
    
    void add(long long x, long long y, long long z)
    {
        to[tot] = y;
        w[tot] = z;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void dfs(long long u, long long fa)
    {
        for (int i = head[u]; i; i = nextt[i])
        {
            int v = to[i];
            if (v != fa)
            {
                dfs(v, u);
                num[u] += num[v];
                ans += w[i] * num[v] * (n - num[v]);
            }
        }
        num[u]++;
    }
    
    int main()
    {
        scanf("%lld", &n);
        for (int i = 2; i <= n; i++)
        {
            long long x, y;
            scanf("%lld%lld", &x, &y);
            fa[i] = x;
            d[i] = y;
            add(x, i, y);
        }
        dfs(1, fa[1]);
        printf("%lld
    ", ans);
        scanf("%lld", &m);
        for (int i = 1; i <= m; i++)
        {
            long long a, b;
            scanf("%lld%lld", &a, &b);
            ans += num[a] * (n - num[a]) * (b - d[a]);
            printf("%lld
    ", ans);
            d[a] = b;
        }
    
        return 0;
    }
  • 相关阅读:
    Array
    StringBuffer
    String
    字节流
    正则表达式
    coursera 机器学习 linear regression 线性回归的小项目
    立个FLAG!
    排序题目练习(Ignatius and the Pincess IV、排序、Clock、排名)
    codeforces 1006
    codeforces
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7596498.html
Copyright © 2011-2022 走看看