1 条题解
-
0
记 代表 到 的距离, 代表 到根的距离。对于 到 的路径,我们需要约束的是,对于路径上任何一个点 ,都有 或 。记 和 的 LCA 为 ,我们把它拆成两部分:
-
对于路径 到 上任何一个点 ,有 或 ;
-
对于路径 到 上任何一个点 ,有 或 。
注意到对于一次查询,左边都是相等的,所以只需要对一条链查询右边这个式子( 或 )在 时的最小值即可。为了做到这一点,我们维护其最小值、最小值颜色、不同于最小值颜色的最小值(即“次小值”)即可。
使用斜二倍增优化,预处理复杂度 ,查询复杂度 。实现细节方面,向上可以朴素做,向下可以(自下向上)倍增时记录最后一段不满足的,然后对着结构逐层向下即可。更详细的可以看代码。
#include <bits/stdc++.h> using namespace std; constexpr int N = 1e5 + 9; inline void cmin(int& x, int y) { x > y && (x = y); } struct info { int mn, mnc, mn2; int operator()(int c) const { return c == mnc ? mn2 : mn; } info& operator+=(info to) { if (mn > to.mn) swap(*this, to); return cmin(mn2, to(mnc)), *this; } } vl[2][N], mx[2][N]; int n, m, d[N], fa[N], lb[N], dph[N], a[N]; inline int lca(int u, int v) { if (d[u] < d[v]) swap(u, v); while (d[u] > d[v]) u = u[d[lb[u]] >= d[v] ? lb : fa]; while (u != v) lb[u] != lb[v] ? (u = lb[u], v = lb[v]) : (u = fa[u], v = fa[v]); return u; } int qry1(int u, int z, int b, int t) { auto chk = [&](info x) { return x(b) > t; }; while (d[u] >= d[z]) if (chk(mx[0][u])) u = lb[u]; else if (chk(vl[0][u])) u = fa[u]; else return u; return 0; } int qry2(int u, int z, int b, int t) { auto chk = [&](info x) { return x(b) > t; }; int x = 0; while (d[u] >= d[z]) if (d[lb[u]] >= d[z]) !chk(mx[1][u]) && (x = u), u = lb[u]; else !chk(vl[1][u]) && (x = u), u = fa[u]; if (d[lb[x]] >= d[z]) { while (lb[x] != fa[x]) { int p = fa[x], q = lb[p]; if (!chk(mx[1][q])) x = q; else if (!chk(mx[1][p])) x = p; else break; } } return x; } signed main() { cin.tie(nullptr)->sync_with_stdio(false); cin >> n; for (int i = 2; i <= n; ++i) cin >> fa[i] >> dph[i], dph[i] += dph[fa[i]]; for (int i = 1; i <= n; ++i) cin >> a[i]; for (int i = 1, t; i <= n; ++i) { int p = fa[i], q = lb[p], r = lb[q]; cin >> t, d[i] = d[p] + 1; mx[0][i] = vl[0][i] = {t + dph[i], a[i], INT_MAX}; mx[1][i] = vl[1][i] = {t - dph[i], a[i], INT_MAX}; if (!p || d[p] - d[q] != d[q] - d[r]) lb[i] = p; else { lb[i] = r; mx[0][i] += mx[0][p], mx[0][i] += mx[0][q]; mx[1][i] += mx[1][p], mx[1][i] += mx[1][q]; } } for (cin >> m; m; --m) { int u, v, b, t, z; cin >> u >> v >> b >> t, z = lca(u, v); int ans = qry1(u, z, b, t += dph[u]) ?: qry2(v, z, b, t - (dph[z] << 1)); cout << (ans ?: -1) << '\n'; } return cout << flush, 0; } -
- 1
信息
- ID
- 10975
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者