D32 树上启发式合并 CF600E Lomsat gelral
视频链接:330 树上启发式合并 CF600E Lomsat gelral_哔哩哔哩_bilibili
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #define LL long long using namespace std; int read(){ char c=getchar(); int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; } const int N=1e5+10; // col[x]:节点的颜色编号, son[x]:重儿子, // cnt[i]:颜色编号i的数量 int n,col[N],siz[N],son[N],cnt[N],mx; LL sum,ans[N]; vector<int> e[N]; void dfs1(int x,int fa){ //重链剖分 siz[x]=1; for(int y : e[x]){ if(y==fa) continue; dfs1(y,x); siz[x]+=siz[y]; if(siz[y]>siz[son[x]]) son[x]=y; } } void add(int x,int fa,int son){ cnt[col[x]]++; if(cnt[col[x]]>mx) mx=cnt[col[x]],sum=col[x]; else if(cnt[col[x]]==mx) sum+=col[x]; for(int y : e[x]) //重子树除外 if(y!=fa && y!=son) add(y,x,son); } void sub(int x,int fa){ cnt[col[x]]--; for(int y : e[x]) if(y!=fa) sub(y,x); } void dfs2(int x, int fa, int opt){ for(int y : e[x]) //先搜轻儿子 if(y!=fa && y!=son[x]) dfs2(y,x,0); if(son[x]) dfs2(son[x],x,1); //后搜重儿子 add(x,fa,son[x]); //累加x和轻子树贡献 ans[x]=sum; //存储答案 if(!opt)sub(x,fa),sum=mx=0; //减掉轻子树贡献 } int main(){ n=read(); for(int i=1; i<=n; i++) col[i]=read(); for(int i=1; i<=n-1; i++){ int x=read(),y=read(); e[x].push_back(y); e[y].push_back(x); } dfs1(1,0); dfs2(1,0,0); for(int i=1; i<=n; i++) printf("%lld ",ans[i]); return 0; }

#include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define LL long long const int N=2e5+10; // col[x]:节点的颜色编号, son[x]:重儿子, // cnt[i]:颜色编号i的数量 int n,col[N],siz[N],son[N],cnt[N]; LL sum,ans[N]; vector<int> e[N]; void dfs1(int x,int fa){ //重链剖分 siz[x]=1; for(int y : e[x]){ if(y==fa) continue; dfs1(y,x); siz[x]+=siz[y]; if(siz[y]>siz[son[x]]) son[x]=y; } } void add(int x,int fa,int son){ if(!cnt[col[x]]) ++sum; cnt[col[x]]++; for(int y : e[x]) //重儿子除外 if(y!=fa && y!=son) add(y,x,son); } void sub(int x,int fa){ cnt[col[x]]--; for(int y : e[x]) if(y!=fa) sub(y,x); } void dfs2(int x, int fa, int opt){ for(int y : e[x]) //先搜轻儿子 if(y!=fa && y!=son[x]) dfs2(y,x,0); if(son[x]) dfs2(son[x],x,1); //后搜重儿子 add(x,fa,son[x]); //累加x和轻子树贡献 ans[x]=sum; //存储答案 if(!opt) sub(x,fa),sum=0; //减掉轻子树贡献 } int main(){ scanf("%d",&n); for(int i=1; i<n; i++){ int u,v; scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } for(int i=1; i<=n; i++) scanf("%d",&col[i]); dfs1(1,0); dfs2(1,0,0); for(int i=1; i<=n; i++) printf("%d\n",ans[i]); return 0; }
分类:
D 图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2022-08-08 C09【模板】可持久化字典树(Trie)