CF893F Subtree Minimum Query
由不超过 \(k\) 层的的点的最小值可以想到用主席树。建立时间线为深度,横轴为时间戳,维护区间最小值的主席树。记 \(dep_x\) 为点 \(x\) 的深度,\(dfn_x\) 为访问到点 \(x\) 的 dfs 序,\(siz_x\) 为以 \(x\) 为根的子树的大小(包括点 \(x\)),每次只需查询 \(dep_x+k\) 层的树中下标为 \([dfn_x,dfn_x+siz_x-1]\) 的区间最小值即可。
注意了每个点得按深度递增的顺序加入到主席树中,还有就是 \(dep_x+k\) 可能大于最大深度。
代码:
#include <bits/stdc++.h>
#define ls son[p][0]
#define rs son[p][1]
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define ll long long
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
inline int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') f = c == '-' ? -1 : f, c = getchar();
while (c >= '0' && c <= '9') x = (x<<3)+(x<<1)+(c^48), c = getchar();
return x*f;
}
inline void write(int x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x/10);
putchar('0'+x%10);
}
const int N = 1e5+5, M = N*50;
int n, m, lst, idx, cnt, root, a[N], d[N], p[N], rt[N], dfn[N], siz[N], val[M], son[M][2];
vector <int> e[N];
inline void dfs(int x, int fa) {
d[x] = d[fa]+1, siz[x] = 1, dfn[x] = ++idx;
for (int y:e[x]) if (y != fa) dfs(y, x), siz[x] += siz[y];
}
inline bool cmp(int x, int y) { return d[x] < d[y]; }
inline void modify(int &p, int q, int l, int r, int x, int v) {
p = ++cnt, ls = son[q][0], rs = son[q][1], val[p] = val[q];
if (l == r) return (void)(val[p] = v);
int mid = l+r>>1;
x <= mid ? modify(ls, son[q][0], l, mid, x, v) : modify(rs, son[q][1], mid+1, r, x, v);
val[p] = min(val[ls], val[rs]);
}
inline int query(int p, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return val[p];
int mid = l+r>>1, res = 0x7f7f7f7f;
if (ql <= mid) res = min(res, query(ls, l, mid, ql, qr));
if (mid < qr) res = min(res, query(rs, mid+1, r, ql, qr));
return res;
}
int main() {
memset(val, 0x7f, sizeof(val));
n = read(), root = read();
for (int i = 1; i <= n; ++i) a[i] = read(), p[i] = i;
for (int i = 1; i < n; ++i) {
int x = read(), y = read();
e[x].pb(y), e[y].pb(x);
}
dfs(root, 0);
sort(p+1, p+n+1, cmp);
for (int i = 1; i <= n; ++i) modify(rt[d[p[i]]], rt[d[p[i-1]]], 1, n, dfn[p[i]], a[p[i]]);
m = read();
while (m--) {
int x = (read()+lst)%n+1, k = (read()+lst)%n;
write(lst = query(rt[min(d[x]+k, d[p[n]])], 1, n, dfn[x], dfn[x]+siz[x]-1)), enter;
}
return 0;
}