本题可以考虑dfs序将树映射到顺序表上,这么做方便线段树操作一个节点和他的所有子孙节点,注意是所有子孙节点。 这时考虑一个问题,如果一下子把所有元素都映射上去,并不能依赖线段树解决涉及深度浅节点的询问。 可以将深度深的节点对应的顺序表元素先置0,等需要它了再放进去,这就需要dfs预处理顺序表(即线段树专用表)和节点的映射关系,同时也要处理每个节点的子孙节点的个数,这两步操作类似传统树链剖分题的与处理环节。 从涉及深度浅的查询开始下手,假设查询是节点x开始往后y步,遂que(1,n,1,pos[x],pos[x]+num[x]-1)查询节点x的所有子孙节点中的最大值,注意这时深度大于y的x的子孙节点尚未置入,即0,对答案不构成影响。可以考虑给查询排序。 如果不给查询排序,主席树应该也可以做,只不过这个做法已经很头大了。 另外好像不涉及区间改动的线段树无需build()建树? 本人赛后补题。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long;
#define nm(a,b) ll a,b;cin>>a>>b;
#define rep(i,a,b) for(ll i=a;i<=b;++i)
#define g(n) ll n;cin>>n;
#define N 500001
ll to[2 * N], nxt[2 * N], node[N], dep[N], num[N], pos[N], vis[N];ll cnt = 0;ll ma = -1;ll top = 0;
ll val[500001 << 4]; ll v[N];
inline void add(ll a, ll b) {
to[cnt] = b;
nxt[cnt] = node[a];
node[a] = cnt++;
}
ll pre_dfs(ll x) {
ma = max(ma, dep[x]);
num[x] = 1;
pos[x] = ++top;
for (int i = node[x]; i; i = nxt[i]) {
int j = to[i];
if (!vis[j]) {
vis[j] = 1;
dep[j] = dep[x] + 1;
num[x] += pre_dfs(j);
}
}
return num[x];
}
void update(ll l, ll r, ll x, ll pos, ll v) {
if (l == r) {
val[x] = max(val[x], v); return;
}
ll mid = l + r >> 1;
if (pos <= mid)update(1, mid, x << 1, pos, v);
else update(mid + 1, r, x << 1 | 1, pos, v);
val[x] = max(val[x << 1], val[x << 1 | 1]);
}
ll que(ll l, ll r, ll x, ll cl, ll cr) {
if (cl <= l && r <= cr) {
return val[x];
}
ll ret = -1;
ll mid = l + r >> 1;
if (cl <= mid)ret = que(1, mid, x << 1, cl, cr);
if (cr > mid)ret = max(ret, que(mid + 1, r, x << 1 | 1, cl, cr));
return ret;
}
ll ans[N];
int main() {
g(n);
rep(i, 1, n) {
cin >> v[i];
}
rep(i, 1, n - 1) {
nm(x, y);
add(x, y);
add(y, x);
}
vis[1] = 1;
dep[1] = 1;
ll ppp = -1;
pre_dfs(1);
vector<vector<pair<ll, ll> > >query(ma + 1);
g(xxx);
rep(i,1,xxx) {
nm(a, b);
query[dep[b] + a].push_back({ b,i });
}
mst(vis, 0);
queue<ll> q;
q.push(1);
vis[1] = 1;
while (!q.empty()) {
auto p = q.front();
q.pop();
if (query[dep[p] - 1].size()) {
for (auto& it : query[dep[p] - 1]) {
ans[it.f2] = que(1, n, 1, pos[it.f1], pos[it.f1] + num[it.f1] - 1);
}
query[dep[p] - 1].clear();
}
update(1, n, 1, pos[p], v[p]);
for (int i = node[p]; i; i = nxt[i]) {
int j = to[i];
if (!vis[j]) {
vis[j] = 1;
q.push(j);
}
}
}
if (query[ma].size()) {
for (auto& it : query[ma]) {
ans[it.f2] = que(1, n, 1, pos[it.f1], pos[it.f1] + num[it.f1] - 1);
}
}
rep(i, 1, xxx) {
cout << ans[i] << endl;
}
}