套用长链剖分板子...
复杂度为
#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
#define fi first
#define se second
#define empb emplace_back
#define all(x) (x).begin(),(x).end()
const int N = 1e5 + 100;
struct node_t {
ll a[2];
const ll &operator [](int i)const { return a[i];}
ll &operator [] (int i) { return a[i];}
void init(ll x) {
a[0] = 1;
a[1] = x;
}
node_t& operator += (const node_t &rhs) {
a[0] += rhs[0], a[1] += rhs[1];
return *this;
}
};
vector<int> E[N];
int n, k;
int a[N], dep[N], son[N];
void prepare(int u, int f) {
for(auto &v : E[u]) {
if(v == f) continue;
prepare(v, u);
if(dep[son[u]] < dep[v]) son[u] = v;
}
dep[u] = dep[son[u]] + 1;
}
node_t pool[N], *pt = pool, *dp[N];
// dp[i][j]表示以i为根的子树下距离i为j的点数以及权值和...
// 长链直接继承长儿子,短链暴力转移...
// 对于点u处的答案为\sum_{v} dp[u][i][0]*dp[v][k-i-1][1]+dp[u][i][1]*dp[v][i][0]
ll res[N];
void dfs(int u, int f) {
dp[u] = pt++;
dp[u]->init(a[u]);
if(son[u]) dfs(son[u], u);
for(auto &v : E[u]) {
if(v == son[u] || v == f) continue;
dfs(v, u);
for(int l = 0; l <= dep[v] && l < k - 1; l++) {
if(k - l - 1 > dep[u]) continue;
res[u] += dp[v][l][0] * dp[u][k - l - 1][1];
res[u] += dp[v][l][1] * dp[u][k - l - 1][0];
}
for(int l = 0; l <= dep[v]; l++) {
dp[u][l + 1] += dp[v][l];
}
}
}
int main() {
#ifdef local
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1, u, v; i < n; i++) {
cin >> u >> v;
E[u].push_back(v);
E[v].push_back(u);
}
dep[0] = -1;
prepare(1, 0);
dfs(1, 0);
for(int i = 1; i <= n; i++) {
cout << res[i] << " \n"[i == n];
}
return 0;
} 
京公网安备 11010502036488号