CF1192B Dynamic Diameter 题解

news/2025/1/21 12:23:31/文章来源:https://www.cnblogs.com/JiaY19/p/18238313

思路

静态 \(\text{top tree}\) 板子题。

定义

我们使用簇来表示树上的一个连通块。

可以按照如下方式定义一个簇:

  1. 一个簇可以表示为三元组 \((u,v,E)\),其中 \(u,v\) 为树的节点,称为簇的界点,\(E\) 为一个边的集合,表示该簇包含的边,路径 \((u,v)\) 称作簇路径。
  2. \(u,v\) 分别为上界点与下界点,上界点是一个簇内深度最小的点,下界点则是除去上界点外的界点。
  3. 界点可以通俗的理解为簇与簇的分界点。
  4. 对于树的一条边 \((u,v)\)\((u,v,{(u,v)})\) 是一个簇。
  5. 对于簇 \((u,v,E_1)\) 与簇 \((v,w,E_2)\)\(E_1\cap E_2=\varnothing\),那么 \((u,w,E_1\cup E_2)\) 也是一个簇,这个操作称为 \(\text{compress}\)
  6. 对于簇 \((x,v,E_1)\) 与簇 \((x,w,E_2)\)\(E_1\cap E_2=\varnothing\),那么 \((x,w,E_1\cup E_2)\) (或者 \((x,v,E_1\cup E_2)\))也是一个簇,这个操作称为 \(\text{rake}\)

经典图:

一个感性理解是 \(\text{rake}\) 将簇与簇融合,\(\text{compress}\) 将簇与簇拼接。

这两个操作可以帮助我们将整棵树合并为一个簇。

  • 对于一度点,进行 \(\text{rake}\)
  • 对于二度点,进行 \(\text{compress}\)

收缩过程中,簇的合并结构形成了一个树,我们把这个树称为 \(\text{top tree}\)

现在,这样一个 \(\text{top tree}\) 它的树高有可能是 \(O(n)\) 的。

更优的树

考虑构造一个树高更小的 \(\text{top tree}\)

容易想到的是全局平衡二叉树。

全局平衡二叉树提供了一个分治方案使整棵树的全局平衡二叉树树高为 \(O(\log n)\)

我们同样可以把这个分治方案放在 \(\text{top tree}\) 上。

具体的,将树进行重链剖分。

然后对于轻儿子,先把它们 \(\text{rake}\) 起来。

再对重链分治 \(\text{compress}\),找分割点时,我们按每个点合并完轻儿子后的簇的大小带权找到中点。

这样就可以建出一颗树高为 \(O(\log n)\)\(\text{top tree}\) 了。

关于这道题

建出 \(\text{top tree}\) 后有什么用呢。

我们想线段树一样的操作它

对于动态直径。

我们把每一个簇,维护三个值。

簇内部的最长距离及到两个界点的最长距离。

合并时我们对两种操作分类讨论拼接起来即可。

可以发现,维护直径的方式与线段树维护最大子段和的方式是比较类似的。

这种维护方法就可以支持一些简单的修改,比如此题的修改边权。

时间复杂度:\(O(n\log n)\)

Code

/*! 如果没有天赋,那就一直重复! Created: 2024/06/05 19:58:38
*/
#include <bits/stdc++.h>
using namespace std;#define int long long
#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)const int N = 2e5 + 10;int n, q, w, ct, last, head[N];
int sz[N], sn[N], fa[N], rt[N], dep[N];
struct Node {int u, v, w;
} d[N];
struct edge {int to, nxt;
} e[N << 1];
struct node {enum { UNIT, RAKE, COMP } type;int u, v, sz, ls, rs, fa, ln, mi, un, vn;
} t[N << 1];inline void add(int x, int y) {e[++ct] = {y, head[x]}, head[x] = ct;e[++ct] = {x, head[y]}, head[y] = ct;
}
inline void dfs(int now, int fa) {sz[now] = 1, dep[now] = dep[fa] + 1;for (int i = head[now]; i; i = e[i].nxt) {int x = e[i].to;if (x == fa) continue;dfs(x, now);t[x] = {node::UNIT, now, x, 1};sz[now] += sz[x];if (sz[x] > sz[sn[now]]) sn[now] = x;}
}
inline void pup(int p) {int x = t[p].ls, y = t[p].rs;if (t[p].type == node::RAKE) {t[p].ln = t[x].ln;t[p].mi = max({t[x].mi, t[y].mi, t[x].un + t[y].un});t[p].un = max(t[x].un, t[y].un);t[p].vn = max(t[x].vn, t[x].ln + t[y].un);} else if (t[p].type == node::COMP) {t[p].ln = t[x].ln + t[y].ln;t[p].mi = max({t[x].mi, t[y].mi, t[x].vn + t[y].un});t[p].un = max(t[x].un, t[x].ln + t[y].un);t[p].vn = max(t[y].vn, t[y].ln + t[x].vn);}
}
inline auto rake(int x, int y) {assert(t[x].u == t[y].u);return t[++ct] = {node::RAKE, t[x].u, t[x].v, t[x].sz + t[y].sz, x, y}, t[x].fa = t[y].fa = ct, pup(ct), ct;
}
inline auto comp(int x, int y) {assert(t[x].v == t[y].u);return t[++ct] = {node::COMP, t[x].u, t[y].v, t[x].sz + t[y].sz, x, y}, t[x].fa = t[y].fa = ct, pup(ct), ct;
}
template<typename T, typename Func>
inline int build(T l, T r, Func f) {if (r == l) return 0;if (r == l + 1) return *l;int all = 0, sum = 0;for (auto it = l; it != r; it++) all += t[*it].sz;T mid = l + 1;for (auto it = l; it != r; it++) {sum += t[*it].sz;if (sum <= all / 2) mid = it + 1; else break;}return f(build(l, mid, f), build(mid, r, f));
}
inline void sol(int now, int ff, bool f) {fa[now] = ff;if (sn[now]) sol(sn[now], now, false);for (int i = head[now]; i; i = e[i].nxt)if (e[i].to != sn[now] && e[i].to != fa[now]) sol(e[i].to, now, true);if (f) {vector<int> s1;if (ff) s1.push_back(now);for (int i = sn[now]; i; i = sn[i]) {vector<int> s2{i};for (int j = head[fa[i]]; j; j = e[j].nxt)if (e[j].to != i && e[j].to != fa[fa[i]]) s2.push_back(rt[e[j].to]);s1.push_back(build(s2.begin(), s2.end(), rake));}rt[now] = build(s1.begin(), s1.end(), comp);}
}
inline void upd(int x, int w) {t[x].un = t[x].vn = t[x].mi = t[x].ln = w;while (t[x].fa) {pup(t[x].fa), x = t[x].fa;}
}signed main() {ios::sync_with_stdio(0), cin.tie(0);cin >> n >> q >> w;fro(i, 1, n - 1) {cin >> d[i].u >> d[i].v >> d[i].w;add(d[i].u, d[i].v);}ct = n;dfs(1, 0);sol(1, 0, 1);fro(i, 1, n - 1) {if (dep[d[i].u] > dep[d[i].v])swap(d[i].u, d[i].v);upd(d[i].v, d[i].w);}fro(i, 1, q) {int x, y;cin >> x >> y;x = (x + last) % (n - 1) + 1;y = (y + last) % (w);d[x].w = y;upd(d[x].v, d[x].w);cout << (last = t[rt[1]].mi) << "\n";}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/721740.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谈判专家迅雷BT下载[2.69GB-MKV]加长完整版[HD1280P]

《谈判专家》是由中国导演韩寒执导的一部谈判题材电影,该片于2017年上映。电影讲述了一场关于中国企业与美国公司之间的商业谈判,以及其中涉及到的诸多挑战和困境。本文将对该电影进行全面分析,从剧情、演员表现、影片风格等方面进行讨论。首先,我们来看剧情。电影《谈判专…

走走停停迅雷BT下载[DB-1280P/3.25GBMKV中字]4k高清百度云资源分享

电影《走走停停》:探寻人生的迷茫与自我救赎电影《走走停停》是一部由李安执导,由乔阿尔文主演的心灵探索之旅。这部电影以一个中年男子的迷失和自我救赎为线索,通过对人生中的停顿和挫折的描绘,引发观众对生活意义的思考。故事的主线由两个不同的时间线交织而成,一条是男…

扫黑决不放弃迅雷BT下载[MOV-5.28GB]高清完整版[HD720p/1080p]

电影《扫黑决不放弃》:坚定信念,抗击黑暗的战斗电影《扫黑决不放弃》是一部扣人心弦的动作犯罪电影,由中国著名导演李安执导,讲述了一群有志青年与黑恶势力斗争的故事。影片通过紧凑的剧情和刺激的动作场面,以及深刻的社会寓意,引发观众对正义与邪恶的思考。电影以中国大…

我才不要和你做朋友呢下载/迅雷BT下载[HD-720P/2.65GB]百度云资源

电影《我才不要和你做朋友呢》是一部由导演张华执导的青春成长电影。该片以逗趣的方式,讲述了一个关于友谊和成长的故事。影片中的角色经历了许多挑战和困难,通过彼此之间的支持和理解,他们在成长的路上逐渐成为了真正的朋友。本文将会从影片的剧情、人物塑造以及核心主题等…

初级算法01

用时:42min class Solution {public int removeDuplicates(int[] nums) {/*** 双指针,右指针遍历整个数组,左指针记录有效值*/int l = 0, r = 0;Set<Integer> s = new HashSet<Integer>();for(; r < nums.length; r++){if(s.add(nums[r])){int t = nums[l];n…

无限之环 题解

五星压行大师 \(lyh\) 表示:这是难得能让他的代码长度打破百行大关的题目(182行)。 首先,根据科技与狠活,本题可以黑白染色。源点联向白格,黑格连向汇点。 发现每个格子都可以连向四个方向,所以可以建立四个点,代表水管连到了上下左右四个方向。 设四元组 \((x,y,z,p)\…

7大系统之间的关系

7大系统之间的关系:MES(制造执行系统)、ERP(企业资源规划)、SCM(供应链管理)、WMS(仓库管理系统)、APS(高级计划和排程)、SCADA(监控控制与数据获取)、PLM(产品生命周期管理)

OpenAI正式发布第一个官方.NET版本库的测试版

尽管 Microsoft 和 OpenAI 长期以来一直是紧密相连的合作伙伴,但他们现在才开始为 .NET 开发人员发布官方 OpenAI 库,加入现有的社区库。这项工作的第一个测试版是支持 .NET 6 和 .NET Standard 2.0 的 OpenAI NuGet 包,现在是 2.0.0-beta.3 [1]版本,列出了大约 872,000 次…

玩转树莓派之系统安装篇

手头上刚好有一个树莓派4B介绍 树莓派是树莓派基金会下的一个明星产品(单板计算机),已经迭代到第五代了;它性能强大、开源、拓展性强、体积小,搞物联网开发的人基本都听说过这个玩意!笔者手上刚好有一块4B的板子,让我们一起来玩转树莓派 安装准备 硬件树莓派4B 4G内存版…

Keil uVersion 4单片机开发指南

MDK Keil uVersion 4使用教程,基于STC8H8K64U单片机1 软件安装 双击打开C51V901.exe弹出安装界面,点击Next>>点击同意协议勾选框,接着点击Next>>点击Browse...选择合适的目录,接着点击Next>>按要求填写相关信息,然后点击Next>>软件安装中,等待安…

读AI未来进行式笔记06自动驾驶技术

读AI未来进行式笔记06自动驾驶技术1. 跃层冲击 1.1. 每个社会其实都处于不同的楼层,往往处于更低楼层的社会,要承受来自更高楼层的社会发展带来的更大冲击 2. 驾驶 2.1. 开车时最关键的不是车,而是路 2.2. 人是比机器更脆弱的生命,最微…

嵌入式代码优化技巧

笔者多年来总结的嵌入式代码优化技巧内存管理技巧 1.C/C++工程应尽量避免深拷贝,尽量用浅拷贝(指针或者引用),如果指针需要频繁拷贝,用智能指针是一种不错的选择 2.启用内存池管理线程的内存开销,事先在堆里边分配好,然后快速使用 避免复杂的浮点运算 1.复杂的浮点运算尽…