题目大意:给定一棵 N 个节点的有根树,1 号节点是树的根节点,每个节点有一个颜色。求对于每个节点来说,能够支配整棵子树的颜色之和是多少。支配的定义为对于以 i 为根的子树,该颜色出现的次数不小于任何其他颜色出现的次数。

题解:学会了 dsu on tree。

树上启发式合并算法是一种对暴力的优化算法。对于暴力算法来说,直接遍历每个节点,再遍历该节点对应的子树寻找答案,时间复杂度显然为 \(O(n^2)\)。考虑进行优化,显然对于父节点来说,遍历到的最后一棵子树的贡献可以不用消去,直接加在父节点对应的子树上即可。根据这条性质,每次都选择 i 的重儿子进行直接累加答案贡献,重儿子的定义和求法与树剖中重儿子相同。可以看出对于树上每个节点,在统计答案的时候仅仅遍历了子树内的所有轻边,即:重儿子对应的子树再合并时不需要再次遍历。从全局的角度来说,对于第 i 个节点为根的子树,子树在统计答案时被遍历的次数和该节点到根节点路径上的轻边个数成正比。一共只有 \(O(logn)\) 条轻边,因此,遍历 n 个节点的时间复杂度上界为 \(O(nlogn)\)。

代码如下

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=1e5+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll fpow(ll a,ll b,ll c){ll ret=1%c;for(;b;b>>=1,a=a*a%c)if(b&1)ret=ret*a%c;return ret;}
inline ll read(){
ll x=0,f=1;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
return f*x;
}
/*------------------------------------------------------------*/ vector<int> G[maxn];
int size[maxn],son[maxn];
int n,cor[maxn],cnt[maxn];
bool skip[maxn];
ll mx,now,ans[maxn]; void getsize(int u,int fa){
size[u]=1;
for(auto v:G[u]){
if(v==fa)continue;
getsize(v,u);
if(size[v]>size[son[u]])son[u]=v;
size[u]+=size[v];
}
}
void add(int u,int fa,int val){
cnt[cor[u]]+=val;
if(val>0){
if(cnt[cor[u]]>mx)now=cor[u],mx=cnt[cor[u]];
else if(cnt[cor[u]]==mx)now+=cor[u];
}
for(auto v:G[u]){
if(v==fa||skip[v])continue;
add(v,u,val);
}
}
void dfs(int u,int fa,bool keep){
for(auto v:G[u]){
if(v==fa||v==son[u])continue;
dfs(v,u,0);
}
if(son[u])dfs(son[u],u,1),skip[son[u]]=1;
add(u,fa,1);
ans[u]=now;
if(son[u])skip[son[u]]=0;
if(!keep)add(u,fa,-1),mx=now=0;
} void read_and_parse(){
n=read();
for(int i=1;i<=n;i++)cor[i]=read();
for(int i=1,x,y;i<n;i++){
x=read(),y=read();
G[x].pb(y),G[y].pb(x);
}
}
void solve(){
getsize(1,0);
dfs(1,0,1);
for(int i=1;i<=n;i++)printf("%lld%c",ans[i],i==n?'\n':' ');
}
int main(){
read_and_parse();
solve();
return 0;
}

【CF600E】Lomsat gelral的更多相关文章

  1. 【CF600E】Lomsat gelral(dsu on tree)

    [CF600E]Lomsat gelral(dsu on tree) 题面 洛谷 CF题面自己去找找吧. 题解 \(dsu\ on\ tree\)板子题 其实就是做子树询问的一个较快的方法. 对于子树 ...

  2. 【CF600E】 Lomsat gelral

    CF600E Lomsat gelral Solution 考虑一下子树的问题,我们可以把一棵树的dfn序搞出来,那么子树就是序列上的一段连续的区间. 然后就可以莫队飞速求解了. 但是这题还有\(\T ...

  3. 【CF600E】Lomsat gelral——树上启发式合并

    (题面来自luogu) 题意翻译 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. ci <= n <= 1e5 裸题.统计时先扫一遍得到出 ...

  4. 【CF600E】Lomset gelral 题解(树上启发式合并)

    题目链接 题目大意:给出一颗含有$n$个结点的树,每个节点有一个颜色.求树中每个子树最多的颜色的编号和. ------------------------- 树上启发式合并(dsu on tree). ...

  5. 「CF600E」Lomsat gelral

    传送门 Luogu 解题思路 线段树合并板子题(也可以 dsu on the tree) 好像没什么好讲的,就是要注意开 long long . 细节注意事项 咕咕咕 参考代码 #include &l ...

  6. 【CodeForces】600 E. Lomsat gelral (dsu on tree)

    [题目]E. Lomsat gelral [题意]给定n个点的树,1为根,每个点有一种颜色ci,一种颜色占领一棵子树当且仅当子树内没有颜色的出现次数超过它,求n个答案——每棵子树的占领颜色的编号和Σc ...

  7. 【Codeforces】600E. Lomsat gelral

    Codeforces 600E. Lomsat gelral 学习了一下dsu on tree 所以为啥是dsu而不是dfs on tree??? 这道题先把这棵树轻重链剖分了,然后先处理轻儿子,处理 ...

  8. CF600E Lomsat gelral 和 CF741D Dokhtar-kosh paths

    Lomsat gelral 一棵以\(1\)为根的树有\(n\)个结点,每个结点都有一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号(若有数量一样的,则求编号和). \(n \le 10^ ...

  9. 【主席树启发式合并】【P3302】[SDOI2013]森林

    Description 给定一个 \(n\) 个节点的森林,有 \(Q\) 次操作,每次要么将森林中某两点联通,保证操作后还是个森林,要么查询两点间权值第 \(k\) 小,保证两点联通.强制在线. L ...

随机推荐

  1. Eclipse的智能提示的设置

    智能提示修改方式是: Windows——>Preferences——>Java-->Editor-->Content Asist,在Auto activation trigge ...

  2. C# Note2:委托(delegate) & Lambda表达式 & 事件(event)

    前言 本文主要讲述委托和Lambda表达式的基础知识,以及如何通过Lambda表达式实现委托调用,并阐述.NET如何将委托用作实现事件的方式. 参考:C#高级编程 1.什么是委托(delegate)? ...

  3. 剑指offer(19)二叉树中和为某一值的路径

    题目: 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度大的 ...

  4. yii2的下载安装

    1.直接使用归档文件安装yii2的高级模板: 从 yiiframework.com 下载归档文件. 下载yii2的高级模板的压缩文件, 将yii-advanced-app-2.0.12文件夹复制到项目 ...

  5. Java第一次实训

    package com.wsy.work; public class JudgeNumber { public static void main(String[] args) { int a = 5; ...

  6. Ajax之Jquery封装使用举例

    <html> <head> <meta charset="UTF-8"> <title>登陆页面</title> < ...

  7. 13.kubernetes之pv,pvc,configmap(带补充实例)

    管理存储是管理计算的一个明显问题.该PersistentVolume子系统为用户和管理员提供了一个API,用于抽象如何根据消费方式提供存储的详细信息.为此,我们引入了两个新的API资源:Persist ...

  8. c++ string替换指定字符串

    string fnd = "dataset"; string rep = "labels"; string buf = "d:/data/datase ...

  9. Announcing Windows Template Studio in UWP

    今天,我们很高兴地宣布您的文件→新的通用Windows平台应用程序在Visual Studio - Windows模板工作室中的下一个演变.Windows Template Studio在开发人员调查 ...

  10. Base64 总结

    Base64编码是解决一些无法打印的字符无法显示的问题,将8位的ascii编码转换为6位的表示64个可见字符的算法. 具体而言,首先将编码每三个分成一组,将三个字符转换为总长为24位的二进制 数字,将 ...