一个很标准的淀粉质题。
题目所给的式子,我们可以看做一个树的重心,然后周围点与这个重心的贡献和,然后继续找这个重心的子树的重心,重复上述过程,就是淀粉质了。
但是我们需要注意一点,如果我们在计算贡献时,没有对所给式子的第一项进行从小到大的排序的话,时间复杂度是要退化为N^2的。关于贡献的求法,就是一个点所有子树的距离和,加上这些点的个数乘于该点到重心的距离就是贡献。
那么我们很愉快地解决了这道题,下次再见!!!
#include <bits/stdc++.h>
const int P = 998244353;
int main()
{
std::cin.tie(0);
std::ios::sync_with_stdio(false);
int n; std::cin >> n;
std::vector <int> val(n);
std::vector <int> e[n];
for(int i = 0; i < n; ++i) std::cin >> val[i];
for(int i = 0; i < n - 1; ++i) {
int u, v; std::cin >> u >> v;
u--, v--;
e[u].emplace_back(v);
e[v].emplace_back(u);
}
int root = -1;
long long ans = 0;
std::vector <int> siz(n);
std::vector <int> max_siz(n);
std::vector <int> vis(n,0);
std::vector <std::pair <int, int>> temp;
std::function <void(int, int, int)> get_root = [&] (int u, int fa, int res) {
siz[u] = 1; max_siz[u] = 0;
for(auto v : e[u]) {
if(v == fa || vis[v]) continue;
get_root(v, u, res);
siz[u] += siz[v];
max_siz[u] = std::max(max_siz[u], siz[v]);
}
max_siz[u] = std::max(max_siz[u], res - siz[u]);
if(root == -1 || max_siz[u] < max_siz[root]) root = u;
};
std::function <void(int, int, int)> get_dis = [&] (int u, int fa, int dep) {
temp.push_back({val[u],dep});
for(auto v : e[u]) {
if(v == fa || vis[v]) continue;
get_dis(v, u, dep + 1);
}
};
auto cal = [&] (int u, int fa, int dep) {
temp.clear();
long long res =0 ;
get_dis(u, fa, dep);
std::sort(temp.begin(),temp.end());
long long dis_sum = 0, dis_pre =0;
for(auto v : temp) {
dis_sum += v.second;
}
int len = (int) temp.size();
for(int i = 0; i <len; ++i) {
dis_pre += temp[i].second;
res = (res + 1ll * temp[i].first * (dis_sum - dis_pre) % P) % P;
res = (res + 1ll * temp[i].first * temp[i].second % P * (len - i - 1) % P) % P;
}
return 2ll * res % P;
};
std::function <void(int)> solve = [&] (int u) {
ans += cal(u, -1, 0);
ans %= P;
vis[u] = 1;
for(auto v : e[u]) {
if(vis[v]) continue;
ans -= cal(v, u, 1);
ans += P;
ans %= P;
root = -1;
get_root(v, u, siz[v]);
solve(root);
}
};
get_root(0, -1, n);
solve(root);
std::cout << ans << '\n';
return 0;
}



京公网安备 11010502036488号