CF536E Tavas on the Path 题解
小清新树剖题。
显然不好直接做,离线下来对
时刻保证
发现维护的是一个颜色段信息,考虑树剖套线段树。
线段树每个节点上维护前缀
注意 push up 时左孩子的后缀
#include <cstdio>
#include <algorithm>
#define G int m = p->s + p->t >> 1
using namespace std;
struct E
{
int v, w, t;
} e[200050];
struct S
{
int u, v, l, i;
} k[100050];
pair<int, int> g[100050];
int n, m, c, p, F[100050], K[100050], z[100050], d[100050],
f[100050], s[100050], t[100050], b[100050], h[100050];
bool C(S a, S b) { return a.l < b.l; }
void A(int u, int v, int w)
{
e[++c] = {v, w, h[u]};
h[u] = c;
}
void X(int u)
{
s[u] = 1;
for (int i = h[u], v; i; i = e[i].t)
if (!d[v = e[i].v])
{
f[v] = u;
d[v] = d[u] + 1;
g[v] = {e[i].w, v};
X(v);
s[u] += s[v];
if (s[v] > s[z[u]])
z[u] = v;
}
}
void Y(int u, int g)
{
t[u] = g;
b[u] = ++p;
if (z[u])
Y(z[u], g);
for (int i = h[u], v; i; i = e[i].t)
if ((v = e[i].v) != z[u] && v != f[u])
Y(v, v);
}
struct T
{
T *l, *r;
int s, t, q, x, y, v;
T(int s, int t) : s(s), t(t) {}
void u()
{
v = l->v + r->v;
x = l->v == l->t - l->s + 1 ? l->v + r->x : l->x;
y = r->v == r->t - r->s + 1 ? r->v + l->y : r->y;
q = l->q + r->q - F[l->y] - F[r->x] + F[l->y + r->x];
}
} * r;
T *U(T *x, T *y)
{
if (!x)
return y;
if (!y)
return x;
T *p = new T(x->s, y->t);
p->l = x;
p->r = y;
p->u();
return p;
}
void B(int s, int t, T *&p)
{
p = new T(s, t);
if (s == t)
return void(p->q = F[p->x = p->y = p->v = 1]);
G;
B(s, m, p->l);
B(m + 1, t, p->r);
p->u();
}
void M(int l, T *p)
{
if (p->s == p->t)
return void(p->q = p->x = p->y = p->v = 0);
G;
if (l <= m)
M(l, p->l);
else
M(l, p->r);
p->u();
}
T *Q(int l, int r, T *p)
{
if (l <= p->s && p->t <= r)
return p;
G;
if (l <= m && r > m)
return U(Q(l, r, p->l), Q(l, r, p->r));
if (l <= m)
return Q(l, r, p->l);
if (r > m)
return Q(l, r, p->r);
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i < n; ++i)
scanf("%d", F + i);
for (int i = 1, u, v, w; i < n; ++i)
scanf("%d%d%d", &u, &v, &w), A(u, v, w), A(v, u, w);
X(d[1] = 1);
Y(1, 1);
B(1, n, r);
sort(g + 2, g + n + 1);
for (int i = 0; i < m; ++i)
scanf("%d%d%d", &k[i].u, &k[i].v, &k[i].l), k[i].i = i;
sort(k, k + m, C);
for (int i = 0, j = 1, u, v; i < m; ++i)
{
while (j < n && g[j + 1].first < k[i].l)
M(b[g[++j].second], r);
u = k[i].u;
v = k[i].v;
T *p = 0, *q = 0;
while (t[u] != t[v])
{
if (d[t[u]] > d[t[v]])
p = U(Q(b[t[u]], b[u], r), p), u = f[t[u]];
else
q = U(Q(b[t[v]], b[v], r), q), v = f[t[v]];
}
if (u != v)
{
if (d[u] > d[v])
p = U(Q(b[v] + 1, b[u], r), p);
else
q = U(Q(b[u] + 1, b[v], r), q);
}
if (p)
p = new T(*p), swap(p->x, p->y);
K[k[i].i] = U(p, q)->q;
}
for (int i = 0; i < m; ++i)
printf("%d\n", K[i]);
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工具