核心思想
借用了一个节点到根的路径上轻边个数不会超过logn条。
故重节点保留,轻节点删去,多重统计。
实际复杂度(nlogn)
例题
Lomsat gelral - 洛谷
AC 代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int col[100010],ans[100010];
vector<int> g[100010];
int son[100010];
int sz[100010];
int sum,mx;
int Son;
int cnt[100010];
void dfs1(int u,int fa){
sz[u] = 1;
for(int v:g[u]){
if(v == fa)continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]){
son[u] = v;
}
}
}
void add(int u,int fa,int val){
cnt[col[u]]+=val;
int tp = col[u];
if(cnt[tp] > mx){
mx = cnt[tp];
sum = tp;
}
else if(cnt[tp] == mx){
sum+=tp;
}
for(int v:g[u]){
if(v == fa||v == Son)continue;
add(v,u,val);
}
}
void dfs2(int u,int fa,int opt){
for(int v:g[u]){
if(v == fa||v == son[u])continue;
dfs2(v,u,0);
}
if(son[u]){
dfs2(son[u],u,1),Son = son[u];
}
add(u,fa,1);Son = 0;
ans[u] = sum;
if(!opt){
add(u,fa,-1),sum = mx = 0;
}
}
signed main(){
cin>>n;
for(int i = 1;i <= n;i++)cin>>col[i];
for(int i = 1;i < n;i++){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(1,0);
dfs2(1,1,0);
for(int i = 1;i <= n;i++){
cout<<ans[i]<<" ";
}
return 0;
}