CF2152H2 Victorious Coloring (Hard Version) 题解

news/2025/10/7 21:03:45/文章来源:https://www.cnblogs.com/Scarab/p/19128874

Description

给定一棵有 \(n\) 个顶点的树,每个顶点编号为 \(1\)\(n\)。每条边都被赋予一个正整数权值 \(w_1, w_2, \ldots, w_{n-1}\)

一种“胜利染色”指的是将所有顶点染成红色或黄色两种颜色,其中必须至少有一个顶点染成红色(这象征着队伍 T1 的象征)。

设对每个顶点分配了一个非负整数权值 \(x_1, x_2, \ldots, x_n\)。胜利染色的代价被定义为:所有红色顶点权值之和,加上所有连接不同颜色顶点(即红色和黄色)之间的边的权值之和。定义 \(f([x_1, x_2, \ldots, x_n])\) 为所有胜利染色下可能的最小代价。

Gumayusi 考虑了在给定序列 \(x_1, x_2, \ldots, x_n\) 时计算 \(f([x_1, x_2, \ldots, x_n])\) 的问题。但对他而言这个问题太简单了,于是他改进了这个问题:给定一个整数 \(l\),求一组非负整数顶点权值 \([x_1, x_2, \ldots, x_n]\),使得 \(f([x_1, x_2, \ldots, x_n]) \ge l\) 且顶点权值总和 \(\sum_{i=1}^n x_i\) 最小。

Gumayusi 感到满意,但还存在一个严重问题——这个问题没有任何询问,对于任何不是“坏的”题目来说是不可接受的。因此,他给这个问题增加了询问。每给定一个 \(l\) 作为询问,你需要输出相应的最小总顶点权值。

\(1\leq n,q\leq 2.5\times 10^5\)

Solution

\(g(S)\) 表示选择 \(S\) 点集内的点染红的边权代价和,那么问题实际上等价于选择一些互不相交的集合 \(S_1,S_2,\ldots,S_k\),最大化 \(\sum(l-g(s_i))\)

首先容易发现最优划分中 \(S\) 一定构成一个连通块,否则随便选择任意一个连通块 \(T\)\(g(T)\) 值一定小于 \(g(S)\),最终的结果也就更大。

还有一个结论是如果存在两条边 \(e_1\)\(e_2\),满足 \(e_1\) 两个端点都在 \(S\) 中,\(e_2\) 恰有一个端点在 \(S\) 中,则一定满足 \(w(e_1)>w(e_2)\)。否则把 \(e_1\) 断掉会把 \(S\) 划分成两个集合 \(S_1\)\(S_2\),选择不包含 \(e_2\) 的端点的那个集合,那么 \(g\) 值一定会至少减少 \(w(e_2)-w(e_1)\geq 0\),矛盾。

注意到如果我们固定最优划分集合 \(S\) 邻域中边权最小的边是 \(e\) 后,只会有至多两个集合满足条件!这是因为 \(e\) 只有两个端点,这两个集合就是两边分别走边权大于 \(w(e)\) 的边后能走到的连通块。


由于这个很类似最大生成树,所以考虑建出边权从大到小的 kruskal 重构树。那么每次选择的集合一定构成一个子树。

每个子树的 \(g\) 值容易树上差分求,设 \(s_u\) 表示 \(u\) 选择子树的 \(g\) 值,\(f_u\) 表示 \(u\) 子树能选择的最大 \(\sum(k-s_u)\)

容易得到转移:\(f_u\leftarrow \max(f_{ls_u}+f_{rs_u},k-s_u)\),直接转移是 \(O(nq)\) 的。

优化就考虑最终的答案一定是由 \(k\cdot i+w\) 的形式构成的,设 \(g_{u,i}\) 表示 \(u\) 的子树中系数为 \(i\) 的最大 \(w\) 值。

转移变为 \(g_{u,i+j}\leftarrow g_{ls_u,i}+g_{rs_u,j},g_{u,1}\leftarrow -s_u\),经打表发现这个东西是凸的,所以可以优先队列+启发式合并维护差分数组,询问时二分即可。

时间复杂度:\(O(n\log^2n+q\log n)\)

Code

#include <bits/stdc++.h>#define int int64_tconst int kMaxN = 5e5 + 5;int n, q, cnt, k;
int u[kMaxN], v[kMaxN], w[kMaxN], fa[kMaxN], id[kMaxN], s[kMaxN];
int ls[kMaxN], rs[kMaxN], f[kMaxN];
std::priority_queue<int> qq[kMaxN];
// int f[kMaxN];
// int sz[kMaxN], g[5005][5005];inline void chkmax(int &x, int y) { x = (x > y ? x : y); }
inline void chkmin(int &x, int y) { x = (x < y ? x : y); }int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);
}void unionn(int x, int y, int w) {int fx = find(x), fy = find(y);if (fx != fy) {++cnt, ls[cnt] = id[fx], rs[cnt] = id[fy], s[cnt] = s[id[fx]] + s[id[fy]] - 2 * w;fa[fx] = fy, id[fy] = cnt;}
}void build() {cnt = n;for (int i = 1; i <= n; ++i) fa[i] = id[i] = i;std::vector<std::tuple<int, int, int>> ed;for (int i = 1; i < n; ++i) ed.emplace_back(w[i], u[i], v[i]);std::sort(ed.begin(), ed.end(), std::greater<>());for (auto [w, u, v] : ed) {unionn(u, v, w);}
}void _dfs(int u) {for (; qq[u].size(); qq[u].pop()) {}if (u <= n) {qq[u].emplace(-s[u]);} else {_dfs(ls[u]), _dfs(rs[u]);if (qq[ls[u]].size() < qq[rs[u]].size()) qq[ls[u]].swap(qq[rs[u]]);qq[u].swap(qq[ls[u]]);for (; qq[rs[u]].size(); qq[rs[u]].pop()) qq[u].emplace(qq[rs[u]].top());if (qq[u].top() < -s[u]) {int lst = qq[u].top();qq[u].pop();if (qq[u].size()) {int x = qq[u].top() + lst;qq[u].pop(), qq[u].emplace(x + s[u]);}qq[u].emplace(-s[u]);}}// std::cerr << "??? " << u << ' ' << ls[u] << ' ' << rs[u] << ' ' << s[3] << ' ' << s[5] << ' ' << s[6] << '\n';// auto tmp = qq[u];// for (; tmp.size(); tmp.pop()) std::cerr << tmp.top() << ' ';// std::cerr << '\n';
}int solve(int k) {// assert(cnt == 2 * n - 1);// ::k = k, dfs(cnt);// return f[cnt];// int ret = 0;// for (int i = 0; i <= n; ++i) chkmax(ret, k * i + f[i]);// return ret;int L = 0, R = n + 1, res = 0;while (L + 1 < R) {int mid = (L + R) >> 1;if (k * mid + f[mid] > k * (mid - 1) + f[mid - 1]) L = res = mid;else R = mid;}return k * res + f[res];
}void dickdreamer() {std::cin >> n;std::fill_n(s + 1, n, 0);for (int i = 1; i < n; ++i)std::cin >> u[i] >> v[i] >> w[i], s[u[i]] += w[i], s[v[i]] += w[i];build();_dfs(cnt);assert(qq[cnt].size() == n);for (int i = 1; i <= n; ++i) f[i] = f[i - 1] + qq[cnt].top(), qq[cnt].pop();std::cin >> q;for (int i = 1; i <= q; ++i) {int k;std::cin >> k;std::cout << solve(k) << '\n';}
}int32_t main() {
#ifdef ORZXKRfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifstd::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);int T = 1;std::cin >> T;while (T--) dickdreamer();// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";return 0;
}

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

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

相关文章

题解:P6162 [Cnoi2020] 四角链

传送门 绝大多数的计数题都可以用 dp 和容斥解决。 本题的 dp 比较好想,设 \(f_{i,j}\) 表示前 \(i\) 个位置填了 \(j\) 个数。考虑如果第 \(i\) 个位置不填,则贡献是 \(f_{i-1,j}\);否则前面 \(i-1\) 个位置一共填…

题解:P3301 [SDOI2013] 方程

传送门 首先如果没有任何限制条件,则原问题即变为简单的「求方程 \(\sum_{i=1}^nx_i=m\) 的解的个数」。此时考虑插板法,等价于将 \(m\) 个 \(1\) 分成 \(n\) 份,这时有 \(m-1\) 个空隙,要插 \(n-1\) 个板,方案数…

# 20232321 2025-2026-1 《网络与系统攻防技术》实验一实验报告

1.实验内容1.1直接修改程序机器指令,改变程序执行流程————通过直接修改可执行文件改变流程 1.2通过构造输入参数,造成BOF攻击,改变程序执行流————通过利用缓冲区溢出的漏洞,使返回的地址跳转到getshell 1.…

基于深度学习的语音识别高效的系统设计与实现

基于深度学习的语音识别高效的系统设计与实现pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &qu…

[ARC201B] Binary Knapsack 大大背包

思路 第一眼背包, 但是 \(n \leq 2e5\) 和重量 $ 2^{X}, X\in[0,60)$ 。所以不能使用背包 由于重量为 $ 2^{X}$ , 很有可能与二进制有关, 于是按位贪心 开 \(65\) 个优先队列,每个优先队列里存放对应与下标相等的 …

网站开发要什么软件济南抖音推广公司

目录 前言 1-保持小的拉取请求 2-使用拉取请求模板 3-实施响应时间 SLA 4-培训初级和中级工程师 5-设置持续集成管道 6-使用拉取请求审查应用程序 7-生成图表以可视化您的代码更改 前言 代码审查可能会很痛苦软件工程师经常抱怨审查过程缓慢&#xff0c;延迟下游任务&…

宁波做网站建设推广广推科技(北京)有限公司

✅作者简介&#xff1a;大家好&#xff0c;我是 Meteors., 向往着更加简洁高效的代码写法与编程方式&#xff0c;持续分享Java技术内容。 &#x1f34e;个人主页&#xff1a;Meteors.的博客 &#x1f49e;当前专栏&#xff1a;Java微服务 ✨特色专栏&#xff1a; 知识分享 &…

题解:CF1292E Rin and The Unknown Flower

传送门 一道有趣的思维题。 我们从最简单的情况开始考虑:如果还剩下 \(2\) 格电呢? 那么直接询问 \(\texttt{O}\) 和 \(\texttt{H}\),剩下的位置就是 \(\texttt{C}\)。 从以上的朴素做法中我们得到启发:能不能通过…

打印A3大小的PDF文件为A4幅面

Foxit 福昕打印pdf:放大150% 然后把每页旋转180度,保存,打印。方法一: 用 Acrobat Pro DC 旋转。 方法二: 用 illustrator,打开pdf,选择某页,旋转,保存

一个完整的网站建设怎么在58同城上做网站

linux服务器的字符集设置可能影响到网站页面出现 “&#xff1f;&#xff1f;&#xff1f;” 等问号乱码&#xff0c;还有可能导致文件中的汉字部分出现乱码。有两个原因 服务器没有安装 zh_CN.UTF-8 字符集&#xff0c;导致不支持中文&#xff01;服务器虽然装了 zh_CN.UTF-8…

深入解析:SpringBoot-Thymeleaf

深入解析:SpringBoot-Thymeleafpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&qu…

课程总结2

请看下列代码,你发现有什么特殊之处吗? public class MethodOverload { public static void main (String [] args) { System.out.println ("The square of integer 7 is" + square (7)); System.out.prin…

延安网站建设哪家专业深圳多区最新通知

‍作者|张祥威 编辑|德新 多位知情人士告诉HiEV&#xff0c;智能网联汽车准入试点通知&#xff0c;乐观预计将在一个月内发布。试点的推动&#xff0c;意味着国家层面的自动驾驶L3标准随之到来。 「L3标准内容大部分与主机厂相关&#xff0c;由工信部牵头&#xff0c;找了几家…

机器学习:集成学习概念、分类、随机森林 - 实践

机器学习:集成学习概念、分类、随机森林 - 实践2025-10-07 20:45 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display…

sudo docker exec -it backend bash 以交互方式(interactive)进入正在运行的 Docker 容器的命令行环境 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

解码查找算法与哈希表

查找基础概念 查找的定义 查找(又称搜索)是从一组数据中,找出 “关键字与目标值匹配” 的记录的操作;若找到则返回记录的位置(如数组下标),若未找到则返回 “不存在” 标识(如-1)。 查找效率的影响因素数据存…

完整教程:MySQL 如何判断某个表中是否存在某个字段

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025/10/7

2025/10/7休息一天

NVMe IP现状扫盲 - 指南

NVMe IP现状扫盲 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &qu…