题目大意:给定一棵 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. Git本地仓库push至GitHub远程仓库每次输入账户密码问题解决(亲测可行)

    在使用git push命令将本地仓库内容推送至GitHub远程仓库的每一次git都要让我们输入GitHub的用户名和密码.这着实让我们心烦.我们会有疑问,我明明设置了公钥呀!怎么还需要输入账户和密码? ...

  2. linux安装httpd,做文件服务器

    在一个团队或者公司层面上,做一个本地的文件服务器,将网上的资源下载到本地,是有必要的.这将节省其他人的很多下载时间. >>提君博客原创  http://www.cnblogs.com/ti ...

  3. python之路--MySQL 库,表的详细操作

    一 库操作 数据库命名规则 可以由数字,字母,下划线,@, #, $ 区分大小写 唯一性 不能使用关键字如 create  select 不能单独使用数字 最长128位 # 这些是对上次的补充. 二 ...

  4. redis 中主从、哨兵和集群分片模式这三个有什么区别 ?

    集群分片 比如 5主5从,也就是说 数据过来之后会均匀的分配到5台服务器上面,5台服务器上面的数据是不同的,但是每个服务器都有一个从服务器,上面的数据跟这一台主服务器的数据是一样的: 也就是说,对于这 ...

  5. xml-dtd

    dtd用于校验XML的语法. dtd步骤: 1.看XML中有多少个元素,有几个元素,在dtd文件中写几个<!ELEMENT> 2.判断元素是简单元素还是复杂元素 -复杂元素:有子元素的元素 ...

  6. Lodop控件NewPage();测试输出空白页

    LODOP.NewPage();和LODOP.NewPageA();是强制分页语句,两者的区别可查看本博客的相关博文:Lodop强制分页LODOP.NewPage()和LODOP.NewPageA() ...

  7. Eclipse环境配置与快捷命令

    1.VS.Chrome.Eclipse调试命令对比: VS: F5: 继续运行 F10: 单步执行 F11: 进入函数内部 Shift + F11: 由函数内部返回调用处 Chrome: F8: 继续 ...

  8. Spring Security 学习总结

    Spring Security Spring Security是基于Spring提供声明式安全保护的安全性框架.Spring Security提供了完整的安全性解决方案,能够在Web请求级别和方法调用 ...

  9. 搭建YUM仓库

    概述 YUM 主要用于自动安装.升级 rpm 软件包,它能自动查找并解决 rpm 包之间的依赖关系.要功的使用 YUM 工具安装更新软件或系统,就需要有一个包含各种 rpm 软件包的 reposito ...

  10. BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流

    题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...