CF526G Spiders Evil Plan 题解
必选一条端点在直径端点的路径,所以以直径两端点为根建两棵树,考虑一棵树的答案。
需要选出
而必定存在方案使得每条路径都经过根:
所以只需考虑选出哪
长剖,没有必须覆盖
考虑怎么解决
否则考虑
-
换掉第
长的长链 ,此时失去的贡献为 的长度,获得的贡献为 的链底到 的父亲的距离。 -
换掉
上方的长链 ,此时失去的贡献为 的长度,获得的贡献为 的链底到 的父亲的距离。
选更优的一项即可。
#include <cstdio>
#include <algorithm>
#define int long long
using namespace std;
struct E
{
int v, w, t;
} e[200050];
int n, m, c, x, y, d[100050], h[100050];
void A(int u, int v, int w)
{
e[++c] = {v, w, h[u]};
h[u] = c;
}
void D(int u, int k, int &S)
{
if (d[u] > d[S])
S = u;
for (int i = h[u], v; i; i = e[i].t)
if ((v = e[i].v) != k)
d[v] = d[u] + e[i].w, D(v, u, S);
}
struct O
{
int z[100050], d[100050], f[100050], s[100050], t[100050], w[100050], o[100050], r[100050], W[100050], T[100050][20];
void D(int u, int k)
{
s[u] = d[u];
for (int i = h[u], v; i; i = e[i].t)
if ((v = e[i].v) != k)
{
d[v] = d[f[v] = u] + e[i].w;
D(v, u);
s[u] = max(s[u], s[v]);
if (s[v] > s[z[u]])
z[u] = v;
}
}
void D1(int u, int k)
{
t[u] = k;
if (z[u])
D1(z[u], k);
else
{
w[t[u]] = d[u] - d[f[t[u]]];
return;
}
for (int i = h[u], v; i; i = e[i].t)
if ((v = e[i].v) != f[u] && v != z[u])
D1(v, v);
}
void B(int x)
{
D(x, 0);
D1(x, x);
for (int i = 1; i <= n; ++i)
o[i] = i;
sort(o + 1, o + n + 1, [&](int x, int y)
{ return w[x] > w[y]; });
for (int i = 1; i <= n; ++i)
W[r[o[i]] = i] = W[i - 1] + w[o[i]];
for (int i = 1; i <= n; ++i)
if (i == t[i])
T[i][0] = t[f[i]];
for (int j = 1; j <= 19; ++j)
for (int i = 1; i <= n; ++i)
T[i][j] = T[T[i][j - 1]][j - 1];
}
int G(int x, int k)
{
for (int j = 19; j >= 0; --j)
if (r[T[x][j]] > k)
x = T[x][j];
return x;
}
int Q(int x, int k)
{
k = min((k << 1) - 1, n);
if (r[t[x]] <= k)
return W[k];
if (k == 1)
return s[x];
int y = o[k], z = G(t[x], k);
return W[k] + max(-w[y] + s[x] - d[f[z]], -w[T[z][0]] + s[x] - d[f[T[z][0]]]);
}
} X, Y;
signed main()
{
scanf("%lld%lld", &n, &m);
for (int i = 1, u, v, w; i < n; ++i)
scanf("%lld%lld%lld", &u, &v, &w), A(u, v, w), A(v, u, w);
D(1, 0, x);
for (int i = 1; i <= n; ++i)
d[i] = 0;
D(x, 0, y);
X.B(x);
Y.B(y);
for (int i = 0, x, k, z = 0; i < m; ++i)
scanf("%lld%lld", &x, &k), x = (x + z - 1) % n + 1, k = (k + z - 1) % n + 1, printf("%lld\n", z = max(X.Q(x, k), Y.Q(x, k)));
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具