洛谷 P2971 [USACO10HOL] Cow Politics G 题解
怎么没有树上启发式合并的题解呢?我来发一篇吧!
简化题意
给定一棵 \(n\) 个点的树,每个点属于 \(k\) 种颜色之一(每种颜色至少有 2 个点)。求每种颜色中,任意两点间的最大距离。
核心思想
树上两点 \(u,v\) 间的距离为 \(dep_u+dep_v-2×dep_{lca(u,v)}\)。同色节点中的最大距离一定对应其中两个节点。考虑枚举它们的 LCA。
对每个节点 \(u\),若它作为 LCA,则考虑它的所有子树中的同色节点,计算不同子树中的同色节点间的最大距离并更新答案。
算法步骤
使用树上启发式合并,维护每种颜色的深度集合。
- 预处理:计算每个点的深度、子树大小、重儿子,和以它为根子树的 DFS 序区间。
- 启发式合并:
- 处理轻子树,处理后从集合中删除其节点。
- 处理重子树。
- 对每个轻子树,计算其节点与已处理节点的同色最大距离并更新答案,再将其加入集合。
- 将当前节点自身当作一棵轻子树处理。
数据结构
对于每种颜色都开一个动态开点平衡树 multiset 维护这种颜色的节点的深度,支持插入、删除和查询最大值。由于深度可能有重复,因此不能用 set。
复杂度分析
对于时间复杂度,每个节点都会被操作 \(O(\log n)\) 次,每次操作 \(O(\log n)\)。一共 \(n\) 个节点。因此总时间复杂度为 \(O(n \log^2 n)\),可以通过本题数据。
对于空间复杂度,由于所有 multiset 中最多保存 \(n\) 个节点的深度,再加上其他长度为 \(n\) 的数组,总空间复杂度为 \(O(n)\)。
AC Code
#include <bits/stdc++.h>
#define rept(i,a,b) for(int i(a);i<=b;++i)
#define eb emplace_back
using namespace std;
constexpr int N=2e5+5,K=1e5+5;
multiset<int> s[K];
vector<int> g[N];
int id[N],dep[N],l[N],r[N],siz[N],ch[N],a[N],ans[K],tot;
void dfs(int u,int pre){
siz[u]=1,l[u]=++tot,id[tot]=u;
for(int v:g[u]){
if(v==pre) continue;
dep[v]=dep[u]+1;
dfs(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[ch[u]]) ch[u]=v;
}
r[u]=tot;
}
void add(int l,int r){ // 插入一棵子树
rept(i,l,r){
int u=id[i];
s[a[u]].insert(dep[u]);
}
}
void sub(int l,int r){ // 删除一棵子树
rept(i,l,r){
int u=id[i];
// 坑点:如果用s[a[u]].erase(dep[u])则会删除所有等于dep[u]的元素,并不是只删一个
s[a[u]].erase(s[a[u]].find(dep[u]));
}
}
void calc(int l,int r,int lca){ // 更新答案
rept(i,l,r){
int u=id[i];
if(s[a[u]].empty()) continue;
int d=*s[a[u]].rbegin();
ans[a[u]]=max(ans[a[u]],d+dep[u]-(dep[lca]<<1));
}
}
void dsu(int u,int pre){
for(int v:g[u]){ // 处理轻儿子
if(v==pre||v==ch[u]) continue;
dsu(v,u);
sub(l[v],r[v]);
}
if(ch[u]) dsu(ch[u],u); // 重儿子
for(int v:g[u]){
if(v==pre||v==ch[u]) continue;
calc(l[v],r[v],u);
add(l[v],r[v]);
}
// 处理这个节点本身
calc(l[u],l[u],u);
add(l[u],l[u]);
}
int main(){
cin.tie(0)->sync_with_stdio(0);
int n,k,t;
cin>>n>>k;
rept(i,1,n){
cin>>a[i]>>t;
if(t) g[i].eb(t),g[t].eb(i);
}
dfs(1,0);
dsu(1,0);
rept(i,1,k){
cout<<ans[i]<<'\n';
}
return 0;
}
洛谷 P2971 [USACO10HOL] Cow Politics G 题解的更多相关文章
- 洛谷P2886 [USACO07NOV]Cow Relays G (矩阵乘法与路径问题)
本题就是求两点间只经过n条边的最短路径,定义广义的矩阵乘法,就是把普通的矩阵乘法从求和改成了取最小值,把内部相乘改成了相加. 代码包含三个内容:广义矩阵乘法,矩阵快速幂,离散化: 1 #include ...
- 洛谷P1854 花店橱窗布置 分析+题解代码
洛谷P1854 花店橱窗布置 分析+题解代码 蒟蒻的第一道提高+/省选-,纪念一下. 题目描述: 某花店现有F束花,每一束花的品种都不一样,同时至少有同样数量的花瓶,被按顺序摆成一行,花瓶的位置是固定 ...
- HAOI2006 (洛谷P2341)受欢迎的牛 题解
HAOI2006 (洛谷P2341)受欢迎的牛 题解 题目描述 友情链接原题 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之 ...
- 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)
洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...
- 洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速$dp\&Floyd$)
洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速\(dp\&Floyd\)) 标签:题解 阅读体验:https://zybuluo.com/Junl ...
- LCA【洛谷P2971】 [USACO10HOL]牛的政治Cow Politics
P2971 [USACO10HOL]牛的政治Cow Politics 农夫约翰的奶牛住在N (2 <= N <= 200,000)片不同的草地上,标号为1到N.恰好有N-1条单位长度的双向 ...
- 不失一般性和快捷性地判定决策单调(洛谷P1912 [NOI2009]诗人小G)(动态规划,决策单调性,单调队列)
洛谷题目传送门 闲话 看完洛谷larryzhong巨佬的题解,蒟蒻一脸懵逼 如果哪年NOI(放心我这样的蒟蒻是去不了的)又来个决策单调性优化DP,那蒟蒻是不是会看都看不出来直接爆\(0\)?! 还是要 ...
- 洛谷2973 [USACO10HOL]赶小猪Driving Out the Piggi… 概率 高斯消元
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - 洛谷2973 题意概括 有N个城市,M条双向道路组成的地图,城市标号为1到N.“西瓜炸弹”放在1号城市,保证城 ...
- BZOJ4946 & 洛谷3826 & UOJ318:[NOI2017]蔬菜——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4946 https://www.luogu.org/problemnew/show/P3826 ht ...
- 洛谷P1972 [SDOI2009]HH的项链 题解
[SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不 ...
随机推荐
- 一文速通 Python 并行计算:12 Python 多进程编程-进程池 Pool
一文速通 Python 并行计算:12 Python 多进程编程-进程池 Pool 摘要: 在Python多进程编程中,Pool类用于创建进程池,可并行执行多个任务.通过map.apply等方法,将函 ...
- 「Note」树论方向
1. 重链剖分 1.1. 简介 重链剖分将树分割成若干链维护信息,将树的结构转换为线性结构,然后可用其他数据结构维护. 定义以下概念: 重子节点 轻子节点 重边 轻边 重链 某节点的子节点中子树大小最 ...
- Springboot笔记<3> 组件注入注解@Conditional与@import
@Conditional @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean. 创建ConfigConditional类和测试类Conf ...
- Ant Design 的 a-input-number 组件限制最小值和最大值以及限制输入为数值型
1.限制输入最大小值 <a-input-number v-model="form.deviceCpuThreshold" placeholder="请输入CPU阈值 ...
- gitlabrunner之executor配置拉取镜像的账户密码
docker executor $ cat config.toml ...... [[runners]] environment = ["DOCKER_AUTH_CONFIG={\" ...
- PHP判断PC还是手机登录
<?php function isMobile(){ $useragent=isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AG ...
- DBA备库工具:Oracle环境中表空间全自动扩容
我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效 ...
- Asp.Net Core MVC 记住密码
https://www.cnblogs.com/Hmd528/p/10695156.html if (lm.RememberMe) { ...
- doget高速下载 github release
平常下载github release或者国外文件时,可能遇到下载速度慢,不能下载等情况. 第一步 打开高速下载网站:https://doget.nocsdn.com 第二步 将文件地址输入进去,然后回 ...
- Nextcloud Error - access through untrusted domain
最近虚拟机的地址更改了,然后发现NextCloud就不可用了.报错如下: 根据报错里的提示来找到config.php. [root@localhost nextcloud]# find / -xdev ...