dsu on tree学习笔记
持续更新 但愿不咕
即树上启发式合并 一般用来解决不带修的子树询问问题
具体看一道题吧 CF600E Lomsat gelral
首先重链剖分确实是一个很神奇的东西 我们的
首先这题非常暴力的一个做法就是对于每个点暴力统计它的子树里的答案 然后清空
这样的复杂度是
我们考虑优化 进行
轻儿子都走完了再走重儿子 统计它的答案然后不清空
然后我们再走所有的轻儿子并且统计答案
这样的复杂度为什么是对的呢 其实可以用重链剖分来理解
需要用到那个我不会证的结论
对于一个点 它到根节点的路径上只会有不超过
条重链
我们考虑一个点都什么时候会被统计答案
对于一个轻儿子 我们都需要走这条轻边 然后把它子树里的点都暴力一遍
那么实际上对于一个点而言 它被统计的次数就是它到根节点路径上轻边的数量
又因为连接重链的就是轻边 所以它到根节点的路径上只有不超过
那我们有
code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 0721;
int siz[N], son[N]; //求重儿子用
int head[N], nxt[N << 1], to[N << 1], _cnt; //链前
int cnt[N], maxn; //这题要用
ll sum, ans[N];
int cl[N];
int n;
inline void add_edge(int x, int y) {
to[++_cnt] = y;
nxt[_cnt] = head[x];
head[x] = _cnt;
}
void get_Gson(int x, int fa) { //求重儿子
siz[x] = 1;
for (int i = head[x]; i; i = nxt[i]) {
int y = to[i];
if (y == fa) continue;
get_Gson(y, x);
if (siz[y] > siz[son[x]]) son[x] = y;
siz[x] += siz[y];
}
}
void init(int x, int fa) { //清空当前子树内的答案
--cnt[cl[x]];
for (int i = head[x]; i; i = nxt[i]) {
int y = to[i];
if (y == fa) continue;
init(y, x);
}
}
void get_ans(int x, int fa, int p) { //遍历并暴力统计答案
++cnt[cl[x]];
if (cnt[cl[x]] > maxn) {
maxn = cnt[cl[x]];
sum = cl[x];
} else if (cnt[cl[x]] == maxn) sum += cl[x];
for (int i = head[x]; i; i = nxt[i]) {
int y = to[i];
if (y == fa || y == p) continue; //重儿子已经统计过了 所以不走
get_ans(y, x, p);
}
}
void dfs(int x, int fa) {
for (int i = head[x]; i; i = nxt[i]) {
int y = to[i];
if (y == fa || y == son[x]) continue; //先不走重儿子
dfs(y, x);
init(y, x);
sum = maxn = 0; //儿子求完就清空
}
if (son[x]) dfs(son[x], x); //走重儿子 并把答案保留
get_ans(x, fa, son[x]); //走别的儿子 更新答案
ans[x] = sum;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &cl[i]);
for (int i = 1; i < n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
add_edge(x, y);
add_edge(y, x);
}
get_Gson(1, 0);
dfs(1, 0);
for (int i = 1; i <= n; ++i) printf("%lld ", ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具