#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>
#include <numeric>
#include <stack>
#include <vector>
#define lowbit(x) (x & -(x))
using namespace std;
typedef long long LL;
constexpr int mod = 998244353;
constexpr int N = 500010, M = 20;
template <typename Tp1, typename Tp2> inline void cmax(Tp1 &A, const Tp2 &B)
{
if (A < B)
A = B;
return;
}
template <typename Tp1, typename Tp2> inline void cmin(Tp1 &A, const Tp2 &B)
{
if (A > B)
A = B;
return;
}
template <typename Tp1, typename Tp2, int mod = ::mod>
inline void ad(Tp1 &A, const Tp2 &B)
{
A = (A + B) % mod;
return;
}
template <typename Tp1, typename Tp2, int mod = ::mod>
inline void sb(Tp1 &A, const Tp2 &B)
{
A = (A + mod - B) % mod;
return;
}
int ans[N], n, a[N], st[M][N], dep[N], son[N], top[N], k, c[N << 1], fa[N],
siz[N], lg[N];
int L[N], R[N], K[N], stl[N], str[N];
inline void add(const int x, const int val)
{
for (int i = x; i <= k; i += lowbit(i))
cmax(c[i], val);
return;
}
inline void clear(const int x)
{
for (int i = x; i <= k; i += lowbit(i))
c[i] = 0;
return;
}
inline int ask(const int x)
{
int res = 0;
for (int i = x; i; i &= i - 1)
cmax(res, c[i]);
return res;
}
struct node
{
int next, to;
} e[N << 1];
int head[N], es;
void bian(int u, int v)
{
e[++es] = {head[u], v};
head[u] = es;
return;
}
struct cdq_t
{
int a, b, c;
int id, tp;
explicit cdq_t(int _a, int _b, int _c, int _id, int _tp)
: a(_a), b(_b), c(_c), id(_id), tp(_tp)
{
assert(c >= 0 && c <= n);
}
bool operator<(cdq_t A) const
{
if (a != A.a)
return a < A.a;
if (b != A.b)
return b < A.b;
return id > A.id;
}
// auto& operator=(const cdq_t &A)
// {
// a = A.a; b = A.b; c = A.c;
// id = A.id; tp = A.tp;
// // abort();
// return *this;
// }
cdq_t() = default;
int &val() const { return ans[id]; }
} q[N], cpy[N];
void pre()
{
for (int i = 2; i != N; i++)
lg[i] = lg[i >> 1] + 1;
return;
}
void dfs1(int u)
{
siz[u] = 1;
for (int i = head[u]; i; i = e[i].next)
if (const int v = e[i].to; v != fa[u])
{
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
siz[u] += siz[v];
if (siz[v] > siz[son[u]])
son[u] = v;
}
return;
}
void dfs2(int u, int tp)
{
top[u] = tp;
if (son[u])
dfs2(son[u], tp);
for (int i = head[u]; i; i = e[i].next)
if (const int v = e[i].to; v != fa[u] && v != son[u])
dfs2(v, v);
return;
}
int get(int l, int r)
{
int tmp = lg[r - l + 1];
return max(st[tmp][l], st[tmp][r - (1 << tmp) + 1]);
}
void cdq(int l, int r)
{
// for (int i = l; i <= r; i++)
// for (int j = l; j <= r; j++)
// if (q[i].tp == 1 && q[j].tp == 0 && q[i].a <= q[j].a &&
// q[i].b <= q[j].b && q[i].c <= q[j].c)
// cmax(q[j].val(), a[q[i].id]);
// return;
// 这里的注释是暴力,加上这部分代码就是对的
if (l == r)
return;
const int mid = (l + r) >> 1;
cdq(l, mid);
cdq(mid + 1, r);
int i = l, j = mid + 1, tot = l;
while (i <= mid && j <= r)
{
if (q[i].b < q[j].b || (q[i].b == q[j].b && q[i].tp == 1))
{
if (q[i].tp == 1) // 0 = ask 1 = point
add(q[i].c, a[q[i].id]);
cpy[tot++] = q[i++];
}
else
{
if (q[j].tp == 0)
cmax(q[j].val(), ask(q[j].c));
cpy[tot++] = q[j++];
}
}
while (j <= r)
{
if (q[j].tp == 0)
cmax(q[j].val(), ask(q[j].c));
cpy[tot++] = q[j++];
}
for (int p = l; p != i; p++)
if (q[p].tp == 1)
clear(q[p].c);
while (i <= mid)
{
// if (q[i].tp == 0) // 0 = ask 1 = point
// cmax(q[i].val(), ask(q[i].c));
cpy[tot++] = q[i++];
}
// copy(cpy + l, cpy + tot, q + l);
// assert(tot = r + 1);
for (int p = l; p <= r; p++) q[p] = cpy[p];
// for (int p = l; p <= r; p++) cerr << q[p].b << ' ';
// cerr << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
// freopen("query2.in", "r", stdin);
// freopen("out.txt", "w", stdout);
pre();
cin >> n;
for (int i = 1; i != n; i++)
{
int u, v;
cin >> u >> v;
bian(u, v);
bian(v, u);
}
dfs1(dep[1] = 1);
dfs2(1, 1);
auto LCA = [](int x, int y)
{
while (top[x] != top[y])
dep[top[x]] >= dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
return dep[x] <= dep[y] ? x : y;
};
for (int i = 1; i <= n; i++)
{
a[i] = dep[LCA(i, i + 1)];
st[0][i] = dep[i];
}
// for (int i = 1; i <= n; i++) cout << a[i] << ' ';
for (int i = 1; (1 << i) <= n; i++)
for (int j = 1; j + (1 << i) <= n + 1; j++)
st[i][j] = max(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
int T;
cin >> T;
for (int i = 1; i <= T; i++)
{
cin >> L[i] >> R[i] >> K[i];
if (--K[i] == 0)
ans[i] = get(L[i], R[i]);
R[i]--;
}
int cnt = 0;
stack<int> stk;
for (int i = 1; i < n; i++)
stl[i] = str[i] = i;
for (int i = 1; i < n; i++)
{
while (!stk.empty() && a[stk.top()] > a[i])
{
str[stk.top()] = i - 1;
stk.pop();
}
stk.push(i);
}
while (stk.size())
str[stk.top()] = n - 1, stk.pop();
for (int i = n - 1; i >= 1; i--)
{
while (!stk.empty() && a[stk.top()] > a[i])
{
stl[stk.top()] = i + 1;
stk.pop();
}
stk.push(i);
}
while (stk.size())
stl[stk.top()] = 1, stk.pop();
k = n + 1;
for (int i = 1; i <= T; i++)
if (K[i])
{
/*
R[i] <= str[j]
R[i] - K[i] + 1 >= stl[j]
L[i] <= stl[j]
*/
q[++cnt] = cdq_t(n - R[i], n - (K[i] - R[i] - 1), n - L[i], i, 0);
}
for (int i = 1; i < n; i++)
q[++cnt] = cdq_t(n - str[i], n + stl[i], n - stl[i], i, 1);
sort(q + 1, q + cnt + 1);
cdq(1, cnt);
cnt = 0;
for (int i = 1; i <= T; i++)
if (K[i])
{
/*
R[i] <= str[j]
L[i] >= stl[j]
R[i] - L[i] + 1 - K[i] >= 0
*/
q[++cnt] = cdq_t(n - R[i], n + L[i], 1, i, 0);
}
for (int i = 1; i < n; i++)
q[++cnt] = cdq_t(n - str[i], n + stl[i], 1, i, 1);
sort(q + 1, q + cnt + 1);
cdq(1, cnt);
cnt = 0;
for (int i = 1; i <= T; i++)
if (K[i])
{
/*
R[i] >= str[j]
K[i] - 1 <= str[j] - stl[j]
L[i] <= stl[j]
*/
q[++cnt] = cdq_t(n + R[i], n - K[i] + 1, n - L[i], i, 0);
}
for (int i = 1; i < n; i++)
q[++cnt] = cdq_t(n + str[i], n - str[i] + stl[i], n - stl[i], i, 1);
sort(q + 1, q + cnt + 1);
cdq(1, cnt);
cnt = 0;
for (int i = 1; i <= T; i++)
if (K[i])
{
/*
R[i] >= str[j]
L[i] + K[i] <= str[i] + 1
L[i] >= stl[j]
*/
q[++cnt] = cdq_t(n + R[i], n - L[i] - K[i], L[i], i, 0);
}
for (int i = 1; i < n; i++)
q[++cnt] = cdq_t(n + str[i], n - str[i] - 1, stl[i], i, 1);
sort(q + 1, q + cnt + 1);
cdq(1, cnt);
cnt = 0;
for (int i = 1; i <= T; i++)
cout << ans[i] << '\n';
return 0;
}
思路是利用 depLCAi=LRi=mindepLCA(i,i+1),求出数组 {W},然后单调栈求出可能对于每个 i,Wi 是最小值的区间,然后用 cdq 分治
求出单调栈区间与询问区间交长度大于或等于 k−1 且值最大的点的贡献离线做本题。暴力可以过大样例,大概是 cdq 分治
写错了求条。