题目描述

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]);
}
}

最新文章

  1. JUnit4参数的使用
  2. 大前端学习笔记整理【六】this关键字详解
  3. 通过VMwarek可以安装Android_x86
  4. 34-php基础:cookie
  5. 非常的奇葩,终于解决了硬盘从盘盘符消失的问题 http://bbs.gamersky.com/thread-1712710-1-1.html (出处: 游民星空论坛)
  6. 机器学习实战__安装python环境
  7. 比callback更简洁的链式执行promise
  8. VMware vSphere服务器虚拟化实验六 vCenter Server 添加储存
  9. 【百度地图API】建立全国银行位置查询系统(五)——如何更改百度地图的信息窗口内容?
  10. toggle的使用心得
  11. 转载 JDK + Android-SDK + Python + MonkeyRunner 的安装
  12. ERP中自定义报表制作流程
  13. [PHP]算法-跳台阶问题的PHP实现
  14. java之不修改变量的数据类型的处理方式
  15. Android开发之ActionBar
  16. python集合set{ }、集合函数及集合的交、差、并
  17. trustbox文件破解
  18. 简单读取 properties文件
  19. Intel 5 6 7 8系列芯片组介绍
  20. JAVA 使用Comparator接口实现自定义排序

热门文章

  1. malloc() vs new
  2. 【Linux】【Shell】【Basic】字符串操作
  3. 3.使用Spring Data ElasticSearch操作ElasticSearch(5.6.8版本)
  4. 【力扣】122. 买卖股票的最佳时机 II
  5. 30个类手写Spring核心原理之Ioc顶层架构设计(2)
  6. 使用OPC与PLC通讯 一
  7. iOS开发——密码存储之keychain的使用
  8. CF250A Paper Work 题解
  9. sar命令查看网卡流量 (System ActivityReporter系统活动情况报告)
  10. bootstrap栅格例子