CF893F Subtree Minimum Query

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;
}
posted @ 2023-12-22 21:38  123wwm  阅读(35)  评论(0)    收藏  举报