题解:Luogu P9260 [PA 2022] Miny

news/2025/10/20 22:04:15/文章来源:https://www.cnblogs.com/P2441M/p/19153775

题意

给定一棵 \(n\) 个点的树,第 \(i\) 条边 \((a_i,b_i)\) 有边权 \(c_i\),第 \(i\) 个点有一个爆炸半径 \(r_i\)。当一个点被引爆时,所有在该点爆炸半径范围内的点也会被引爆,这些新的被引爆的点也可能继续引爆其他点……对于每个点 \(i\),求出该点被引爆后,最终会被引爆的点的数量。\(1\leq n\leq 10^5\)\(0\leq r_i\leq 10^{18}\)\(1\leq c_i\leq 10^{12}\)

题解

rerererecallllll。

比较毒瘤。

考虑建图,对于每个点 \(i\),向距离它不超过 \(r_i\) 的点 \(j\) 连一条有向边。对这个有向图缩点,考察一个强连通分量,显然引爆其中任何一个点都会让整个强连通分量中的点被引爆,于是每个点的答案就是在这个缩点后的 DAG 中可达的点数。

这样建图边数会爆炸,考虑优化建图。注意到建图条件是距离相关,因此考虑点分治优化建图。具体来说,设当前分治中心为 \(rt\),考察所有 \(rt\) 子树内的点。设 \(dis_u\)\(u\)\(rt\) 的距离,那么对于处于 \(rt\) 不同的儿子子树内的两点 \(u,v\)\(u\)\(v\) 连边的条件为 \(dis_u+dis_v\leq r_u\)。而对于相同儿子子树内的两点,我们同样沿用这个条件即可,因为这相当于把限制放宽松了,并且我们向下递归到两点的 LCA 时,也会正确处理这两个点间的连边。

\(rt\) 子树内所有点按 \(dis\) 排序,枚举点 \(u\),那么它连出去的点 \(v\) 需要满足 \(dis_v\leq r_u-dis_u\),是一段前缀的点。我们可以使用前缀优化建图,建出 \(|sub_{rt}|\) 个虚点,从左到右第 \(i\) 个虚点,向第 \(i-1\) 个虚点连边,同时也要向排序后第 \(i\) 小的点连边。每次枚举点 \(u\) 时我们二分出分界点,向该分界点对应的虚点即可。这样我们就把图的点数和边数都压到了 \(\mathcal{O}(n\log{n})\) 级别,点分治建图的复杂度则是 \(\mathcal{O}(n\log^2{n})\) 的。

把图建出来缩点后,剩下的部分就是 DAG 可达性了。我们当然考虑建反图,在拓扑排序的过程中用 bitset 维护,但是这样子对于每个强连通分量我们都要开一个大小为 \(n\)bitset,时空复杂度都是 \(\mathcal{O}\left(\dfrac{n^2\log{n}}{\omega}\right)\) 的,空间上无法承受。我们不妨分块,设块长为 \(B\),每次取一个长度为 \(\mathcal{O}(B)\) 的编号区间 \([l,r]\) 出来,跑 DAG 可达性时只考虑这里面的点。这样空间复杂度降至 \(\mathcal{O}\left(\dfrac{nB\log{n}}{\omega}\right)\),时间复杂度理论不变。

总体时间复杂度为 \(\mathcal{O}\left(n\log^2{n}+\dfrac{n^2\log{n}}{\omega}\right)\)

这就能通过本题了吗?并不能。本题非常毒瘤,一些未经优化的地方常数是比较大的。接下来讲讲我是如何卡常的。

取不同的 \(B\),时间复杂度只是理论不变,但实际运行中取稍大的 \(B\) 会对内存访问更友好,以我的实现取 \(B=1500\) 较为优秀。

可以发现我们不必显式跑拓扑排序。我们知道 Tarjan 跑出来的强连通分量编号是逆拓扑序,于是可以把 DAG 缩点后的反图中的每条边 \((u,v)\)\(u\) 为第一关键字、\(v\) 为第二关键字排序,跑 DAG 可达性时只需依次访问每条边 \((u,v)\),令 \(f_v\leftarrow f_v\cup f_u\) 即可。这样子没有了建图和遍历出边的开销,常数也优化了不少。

显然只有 \(1\sim n\) 所在的强连通分量是有用的,所以枚举强连通分量时的个数上界,应该设置成 \(1\sim n\) 所在的强连通分量的最大编号。

最后是最显著的优化。前缀优化建图时,\(\mathcal{O}(n\log{n})\) 个虚点带来的开销是巨大的,我们不妨只保留有用的那些。具体来说,对于一轮分治,我们把枚举点 \(u\) 时二分出的那些分界点对应的虚点视作关键点,对于相邻的关键点 \(p_i,p_{i+1}\),把 \([p_i+1,p_{i+1}]\) 中的点全部缩成 \(p_{i+1}\) 这一个点。虽然这样子图的点数和边数的理论量级不变,但是实际数量会显著减少。

加上上面这些优化就跑的飞快了。

代码

这里放出主要的部分。

inline void dfs_rt(int x, int fx, int szrt) {int mxp = 0; sz[x] = 1;for (int i = T.head[x]; i; i = T.nxt[i]) {int y = T.to[i];if (!del[y] && y != fx) dfs_rt(y, x, szrt), sz[x] += sz[y], chk_max(mxp, sz[y]);}chk_max(mxp, szrt - sz[x]);if (mxp << 1 <= szrt) rt = x;
}
inline void dfs_dis(int x, int fx) {sz[x] = 1, pt[++szp] = {dis[x], x};for (int i = T.head[x]; i; i = T.nxt[i]) {int y = T.to[i]; ll z = T.w[i];if (!del[y] && y != fx) dis[y] = dis[x] + z, dfs_dis(y, x), sz[x] += sz[y];}
}
inline void dfs_solve(int x, int szrt) {if (szrt == 1) return;rt = 0, dfs_rt(x, 0, szrt), del[rt] = 1;szp = dis[rt] = 0, dfs_dis(rt, 0);sort(pt + 1, pt + szp + 1), fill(num + 1, num + szp + 1, 0);for (int i = 1; i <= szp; ++i) {int px = pt[i].second; ll dx = dis[px];int p = upper_bound(pt + 1, pt + szp + 1, pli{d[px] - dx, n + 1}) - pt - 1;if (p) {if (!num[p]) num[p] = ++tot;G.ins(px, num[p]);}}int lst = 0;for (int i = szp; ~i; --i) {if (i && !num[i]) continue;if (lst) {if (i) G.ins(num[lst], num[i]);for (int j = i + 1; j <= lst; ++j) G.ins(num[lst], pt[j].second);}lst = i;}for (int i = T.head[rt]; i; i = T.nxt[i]) {int y = T.to[i];if (!del[y]) dfs_solve(y, sz[y]);}
}
inline void tarjan(int x) {low[x] = dfn[x] = ++stmp, in_stk[stk[++top] = x] = 1;for (int i = G.head[x]; i; i = G.nxt[i]) {int y = G.to[i];if (!dfn[y]) tarjan(y), chk_min(low[x], low[y]);else if (in_stk[y]) chk_min(low[x], dfn[y]);}if (low[x] == dfn[x]) {++cscc; int p;do p = stk[top--], id[p] = cscc, in_stk[p] = 0; while (p != x);}
}
inline void solve(int l, int r) {for (int i = 1; i <= mxt; ++i) f[i].reset();for (int i = l; i <= r; ++i) f[id[i]][i - l] = 1;for (int i = 1; i <= sze; ++i) f[edges[i].second] |= f[edges[i].first];for (int i = 1; i <= n; ++i) ans[i] += f[id[i]].count();
}int main() {ios::sync_with_stdio(0), cin.tie(0);n = rd();for (int i = 1; i <= n; ++i) d[i] = rd();ll w; for (int i = 1, u, v; i < n; ++i) u = rd(), v = rd(), w = rd(), T.ins(u, v, w), T.ins(v, u, w);dfs_solve(1, tot = n);for (int i = 1; i <= tot; ++i) if (!dfn[i]) tarjan(i);for (int i = 1; i <= n; ++i) chk_max(mxt, id[i]);for (int x = 1; x <= tot; ++x) for (int i = G.head[x]; i; i = G.nxt[i]) {int y = G.to[i];if (id[x] != id[y]) edges[++sze] = {id[y], id[x]};}sort(edges + 1, edges + sze + 1);for (int i = 1; i <= n; i += B) solve(i, min(i + B - 1, n));for (int i = 1; i <= n; ++i) cout << ans[i] << ' ';return 0;
}

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

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

相关文章

题解:Luogu P13544 [OOI 2022] Serious Business

题意 给定一个 \(3\times n\) 的网格,每个格子 \((i,j)\) 内有一个数 \(a_{i,j}\)。一个人初始分数为 \(0\),在位置 \((1,1)\) 处,每次可以向右或向下走一格,目标是到达 \((3,n)\)。当走到格子 \((i,j)\) 时,这个…

题解:Luogu P14254 分割(divide)

题意 给定一棵 \(n\) 个点的树,设根节点 \(1\) 的深度为 \(1\)。给定 \(k\),求有多少从树中选出 \(k\) 个两两不同的节点,组成有序序列 \(b_1,\cdots,b_k\) 的方案,使得:对于每个 \(1\leq i<k\),\(1<d_{b_…

31_创蓝短信接入资料和定价

创蓝短信接入资料和定价 公司简介 创蓝云智为企业提供短信、语音外呼、闪验、号码检测、实名认证等通讯类产品,致力于让企业更高效高质量的获得用户及触达用户。 产品类型通知短信 会员营销短信 国际营销短信 验证码短…

构造单

题目来源 取模下序列构造 是否存在 \(3\) 个长度为 \(n\) 的 \([0,n)\) 的排列 \(a,b,c\),使得 \(a_i+b_i=c_i\mod n\) 遇到取模考虑奇偶性,不要像太复杂,考虑 \(n\) 为奇数的时候直接 \(a=b=~0,1,2,3,4,…\),\(c=…

02.Python百行代码实现抽奖系统

02.Python百行代码实现抽奖系统 ------------------------------------------------ 执行后——————————————————————————————————————————————————————————…

[笔记]高斯消元

高斯消元法是求解线性方程组的经典算法。 内容 求解如下的线性方程组(P3389 【模板】高斯消元法): \[\begin{cases} a_{1,1}x_1+a_{1,2}x_2+\dots+a_{1,n}x_n=b_1\\ a_{2,1}x_1+a_{2,2}x_2+\dots+a_{2,n}x_n=b_2\\ …

[SSH] scp:基于 SSH 的安全文件传输

[SSH] scp:基于 SSH 的安全文件传输$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");目录01 简介02 操作2.1 本地发送到远程2.2 从远程下载2.3 主机之间复制…

CSP-S 35

10.2010.20 神秘%你赛,rk1 170 ,你管这叫CSP-S? t1 赛时狂写t1 ,想了半天想出来个神秘做法,时间复杂度不会证但应该是对的,写完本地大阳历1.2s 感觉应该没啥大问题,结果空间炸了,最后2h写的代码和暴力分一样多 …

题解:P11662 [JOI 2025 Final] 方格染色 / Grid Coloring

题目传送门 是一道黄题 这里提供一种 \(O(n\log n)\) 的做法\(\mathscr{PART\ \ ONE}\)我们在手%的时候不难发现(注意力有点也不惊人) 虽然第一列和第一行 不保证有序 但是因为这里的前缀$\ max\ $性质保证了第二列和…

CSP-S 32 多校5

10.1510.15 S-32&&多校5 签到后遗憾离场。 t1 签到题,大力分讨即可。 注意符号。 记得排序(没大阳历时忘排序了) code锵锵 #include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10;…

CSP-S 33

10.1710.17 t1 签到题 注意到约数只有 \(O(\sqrt n)\) 级别,暴力找约数即可。 唐人当然有唐做法啦! 分解质因数+dfs搜约数 反正唐就对了。 code嘻嘻 #include <bits/stdc++.h> #define int long long #define…

CSP-S 29

10.11 只记录了当时认为有意义的题10.11 t3 赛后才看懂题面 \(\ldots\) 妈妈我会推式子!(骗你的其实我不会) 推完式子就过了。 考虑先求出 \(1\) 为根时的答案,之后换根即可。 开始拆贡献ing 对于根结点,由于一开…

10.20每日总结

今天主要的课程有软件设计,软件开发案例分析,大数据技术,物联网工程。完成了好几项作业,满课还是太忙太累了,软考网课开始第三章。

CSP-S 31

10.1410.14 看大家得分跟信心赛似的,就我一个唐诗写了一场暴力 \(\ldots\) 开场t1没切出来就开始慌了,之后就想着多打暴力拿部分分,导致t2得出的性质没有推广,t3,t4暴力都没写出来(这俩得出性质/部分性质后比暴力…

2025网络安全振兴杯wp

振兴杯wp web1 神探狄仁杰在js和源代码,以及关于里面有flag的base64字段 css中关于的源代码中然后解密就行了 web2Darksale 这个是一个原型链污染 我们发现购买的金额可以被改变我们发现改价格后会回显出来我们尝试修…

ES原理、zookeeper、kafka

ES原理、zookeeper、kafkaES高级 ES底层原理 协调节点是 Elasticsearch 中接收客户端请求、将请求转发到相关数据节点、并汇总最终结果返回给客户端的中心路由节点 Cluster State 是 Elasticsearch 集群的元数据大脑,…

CF1606E Arena 题解(动态规划)

考虑设 \(f_{i,j}\) 表示现在存活 \(i\) 个人,血量最大的人为 \(j\)。这么设是因为注意到有没有胜者其实之和血量最大的是谁,以及有多少个血量最大的有关。 边界情况 \(f_{1,i}=0\)。 考虑转移。如果 \(j<i\),则…

服务器CPU市场概况2025

2025年的服务器CPU市场正处于关键转型期。传统的x86架构(以Intel和AMD为代表)依然占据主导,但基于Arm的解决方案正在快速崛起。随着人工智能(AI)、云计算和高性能计算(HPC)的普及,CPU的设计趋势正在朝着能效优…

CSP-S 24

9.21~9.2?9.21 今天开始集训告一段落了,去补文化课一周。 如果写不完回来会补(?) 115=100+0+15 t1 先等会 t2 先等会 t3 9.22:回来补债了 \([\gcd(i,j)=1]=[\gcd(p_i,p_j)=1]\) 这个限制初看好像很难转化,只能猜…