题目描述
You are given a rooted tree with root in vertex 11 . Each vertex is coloured in some colour.
Let‘s call colour cc dominating in the subtree of vertex vv if there are no other colours that appear in the subtree of vertex vv more times than colour cc . So it‘s possible that two or more colours will be dominating in the subtree of some vertex.
The subtree of vertex vv is the vertex vv and all other vertices that contains vertex vv in each path to the root.
For each vertex vv find the sum of all dominating colours in the subtree of vertex vv .
题目分析
首先分析问题,发现求得是以当前节点为子树的众数和
考虑dsu,在更新答案时,我们统计每一个数的出现次数,如果大了就更新sum,否则更新次数
具体的dsu,我们可以采取重链剖分的思路
重儿子的大小最大,所以将每一个节点先赋为重儿子,在一次统计轻儿子,最后清空影响
在操作轻儿子时,可以用dfn来遍历
对于时间复杂度,因为\(wson_size>=n/2\) 所以,每一次只会操作\(n/2\),递归后,时间为\(O(n*log2(n))\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e5+5;
int n,q,root;
int a[MAXN];
int lsh[MAXN];
vector<int>g[MAXN];
int x,y;
int sum;
int maxi;
int son[MAXN];
int size[MAXN];
int num[MAXN];
int dfn[MAXN];
int dfnc[MAXN];
int cnt=0;
void dfs1(int x,int fa)
{
dfn[x]=++cnt;
dfnc[cnt]=x;
size[x]=1;
int maxi=0;
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(v==fa)
{
continue;
}
dfs1(v,x);
size[x]+=size[v];
if(maxi<size[v])
{
son[x]=v;
maxi=size[v];
}
}
}
int rec[MAXN];
void dfs(int x,int f,int check)
{
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(v==f||v==son[x])
{
continue;
}
dfs(v,x,0);
}
if(son[x])
{
dfs(son[x],x,1);
}
num[a[x]]++;
if(maxi<num[a[x]])
{
maxi=num[a[x]];
sum=a[x];
}
else if(maxi==num[a[x]])
{
sum+=a[x];
}
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(v==f||v==son[x])
{
continue;
}
for(int j=dfn[v];j<=dfn[v]+size[v]-1;j++)
{
int key=dfnc[j];
num[a[key]]++;
if(maxi<num[a[key]])
{
maxi=num[a[key]];
sum=a[key];
}
else if(maxi==num[a[key]])
{
sum+=a[key];
}
}
}
rec[x]=sum;
// printf("%d %d\n",x,sum);
if(!check)
{
for(int j=dfn[x];j<=dfn[x]+size[x]-1;j++)
{
int key=dfnc[j];
num[a[key]]--;
}
maxi=0;
sum=0;
}
}
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(int i=1;i<n;i++)
{
scanf("%lld %lld",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
dfs1(1,0);
dfs(1,0,0);
for(int i=1;i<=n;i++)
{
printf("%lld ",rec[i]);
}
}