noip模拟赛 蒜头君的树

Posted zbtrs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\\n", 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\\n", ans);
        d[a] = b;
    }

    return 0;
}

 

以上是关于noip模拟赛 蒜头君的树的主要内容,如果未能解决你的问题,请参考以下文章

复习---归并排序求逆序对--计蒜客2017noip模拟赛二--蒜头君的排序

计蒜客模拟赛D1T2 蒜头君的树:树上节点之间最短距离和

蒜头君的树

noip模拟赛 蒜头君打地鼠

蒜头君的坐骑

2019 10.3模拟