F. Subtree Minimum Query
题目大意:给出一颗有根点权树, m m m 次询问,每次问你某个点 x x x 的子树中距离其不超过 k k k 的点的权值的最小值。
以深度为时间轴, d f s dfs dfs 序为下标建立主席树维护区间最小值即可。因为这样第 i i i 层的所代表的主席树就存下了前 i i i 层所有点,我们要找的点会完全包含在里面,且更深层的点还没有被计算进来,所以我们只要找到当前主席树上 x x x 那一颗子树上的区间最小值即可,即可以通过 d f s dfs dfs 序为下标的方式快速询问一颗子树。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, r, a[N], m;
int f[N], dep[N], sz[N], dfn[N], cnt, mxdep;
vector<int> g[N];
int mn[N << 5], lson[N << 5], rson[N << 5], root[N], tot;
queue<int> q;
void dfs(int u, int fa, int d) {
f[u] = fa;
dep[u] = d; mxdep = max(mxdep, d);
dfn[u] = ++cnt;
sz[u] = 1;
for (auto v : g[u]) {
if (v ^ fa) {
dfs(v, u, d + 1);
sz[u] += sz[v];
}
}
}
void push_up(int rt) {
mn[rt] = min(mn[lson[rt]], mn[rson[rt]]);
}
void update(int pre, int &rt, int l, int r, int pos, int v) {
rt = ++tot;
mn[rt] = mn[pre];
lson[rt] = lson[pre];
rson[rt] = rson[pre];
if (l == r) {
mn[rt] = v;
return ;
}
int mid = l + r >> 1;
if (pos <= mid) update(lson[pre], lson[rt], l, mid, pos, v);
else update(rson[pre], rson[rt], mid + 1, r, pos, v);
push_up(rt);
}
int query(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R) {
return mn[rt];
}
int mid = l + r >> 1, ans = 2e9;
if (mid >= L) ans = query(lson[rt], l, mid, L, R);
if (mid < R) ans = min(ans, query(rson[rt], mid + 1, r, L, R));
return ans;
}
void bfs() {
int lst = 0;
q.push(r);
while(!q.empty()) {
int u = q.front();
q.pop();
update(root[dep[lst]], root[dep[u]], 1, n, dfn[u], a[u]);
lst = u;
for (auto v : g[u]) {
if (v ^ f[u]) q.push(v);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
scanf("%d%d", &n, &r);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 1, u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(r, 0, 1);
mn[0] = 2e9;
bfs();
scanf("%d", &m);
int lans = 0;
while(m--) {
int p, q, x, k;
scanf("%d%d", &p, &q);
x = (p + lans) % n + 1;
k = (q + lans) % n;
lans = query(root[min(mxdep, dep[x] + k)], 1, n, dfn[x], dfn[x] + sz[x] - 1);
printf("%d\n", lans);
}
}