600E - Lomsat gelral(找子树多颜色问题)(入门)
2024-09-06 11:29:00
题:https://codeforces.com/problemset/problem/600/E
题意:一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和,对于每个结点都输出答案。
分析:考虑暴力算法,对于每个节点只是清空计数数组,再对其子树颜色进行统计,复杂度o(n^2);
接着我们发现最后一个子树的清空是必要的,所以我们把重儿子当作这个子树,就可以让复杂度降为o(nlogn)级别;
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int M=2e5+;
ll ans[M];
ll countt[M],sz[M],son[M],col[M],vis[M];
vector<int>g[M];
ll nownum,maxx;
void dfs1(int u,int fa){
sz[u]=;
for(int i=;i<g[u].size();i++){
int v=g[u][i];
if(v!=fa){
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])
son[u]=v;
}
}
} void update(int u,int k,int fa){//k的取值为1和-1,分别对应累加和清除
countt[col[u]]+=k;
if(maxx<countt[col[u]])
maxx=countt[col[u]],nownum=col[u];
else if(maxx==countt[col[u]])
nownum+=col[u];
for(int i=;i<g[u].size();i++){
int v=g[u][i];
if(v!=fa&&!vis[v])
update(v,k,u);
}
}
void dfs2(int u,int fa,int sign){
//cout<<u<<endl;
for(int i=;i<g[u].size();i++){
int v=g[u][i];
if(v!=fa&&son[u]!=v)
dfs2(v,u,);
}
if(son[u])//再访问重儿子,一定要打上vis标记
dfs2(son[u],u,),vis[son[u]]=;
update(u,,fa);
ans[u]=nownum;
if(son[u])
vis[son[u]]=;
if(!sign)///轻儿子就消除影响
update(u,-,fa),nownum=maxx=; }
int main(){
int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&col[i]);
for(int u,v,i=;i<n;i++){
scanf("%d%d",&u,&v);
g[u].pb(v);
g[v].pb(u);
}
dfs1(,); dfs2(,,);
for(int i=;i<=n;i++)
printf("%I64d ",ans[i]);
return ;
}
最新文章
- DllImport attribute的总结
- python字符串/元组/列表/字典互转
- VS xsd Class
- 反弹SHELL
- CentOS 6.0修改ssh远程连接端口
- BlockingQueue-线程的阻塞队列
- Qt5.4静态编译方法
- JVM 重排序
- SVN服务器搭建(3)
- 关于MPMoviePlayerController类播放视频时,外放没有声音的问题(ios)
- Java基础-Random类(05)
- centos下 apache+mysql+php的安装
- Gitlab使用时的一些注意事项
- NEO学习笔记,从WIF到地址
- Form数据迁移
- mybatis插入数据后返回对象id
- Windows下使用创建多层文件夹 SHCreateDirectoryEx 函数需要注意的问题
- FFT理解
- 【ASP.NET 进阶】PDF文件在线预览(类似百度文库)
- 线性查找算法(BFPRT)