1. 程式人生 > >CF893F Subtree Minimum Query 主席樹

CF893F Subtree Minimum Query 主席樹

mxd pen update getchar algo char insert ios 最小值

技術分享圖片

如果是求和就很好做了...

不是求和也無傷大雅....

一維太難限制條件了,考慮二維限制

一維$dfs$序,一維$dep$序

詢問$(x, k)$對應著在$dfs$上查$[dfn[x], dfn[x] + sz[x] - 1]$,在$dep$序上查$[dep[x], dep[x] + k]$

這樣子,每個詢問對應查詢一段矩形內的最小值

然而樹套樹是過不了的.....

發現一個詢問看似在$dep$序上對應了一段區間,實際上可以擴展到對應一段前綴

這樣子,只需要一個主席樹就可以做到了

復雜度$O(n \log n)$

#include <map>
#include 
<queue> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> namespace remoon { #define ri register int #define tpr template <typename ra> #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++) #define
drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --) #define gc getchar inline int read() { int p = 0, w = 1; char c = gc(); while(c > 9 || c < 0) { if(c == -) w = -1; c = gc(); } while(c >= 0 && c <= 9) p = p * 10 + c - 0, c = gc();
return p * w; } int wr[50], rw; #define pc(iw) putchar(iw) tpr inline void write(ra o, char c = \n) { if(!o) pc(0); if(o < 0) o = -o, pc(-); while(o) wr[++ rw] = o % 10, o /= 10; while(rw) pc(wr[rw --] + 0); pc(c); } tpr inline void cmin(ra &a, ra b) { if(a > b) a = b; } tpr inline void cmax(ra &a, ra b) { if(a < b) a = b; } tpr inline bool ckmin(ra &a, ra b) { return (a > b) ? a = b, 1 : 0; } tpr inline bool ckmax(ra &a, ra b) { return (a < b) ? a = b, 1 : 0; } } using namespace std; using namespace remoon; #define sid 300050 #define oid 12050000 int dfn[sid], sz[sid]; int n, r, m, id, tim, cnp, mxd; int rt[sid], nxt[sid], node[sid], cap[sid]; int fa[sid], q[sid], w[sid], dep[sid]; int ls[oid], rs[oid], miv[oid]; inline void addedge(int u, int v) { nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v; } #define cur node[i] inline void dfs(int o, int f) { fa[o] = f; dep[o] = dep[f] + 1; sz[o] = 1; dfn[o] = ++ tim; for(int i = cap[o]; i; i = nxt[i]) if(cur != f) dfs(cur, o), sz[o] += sz[cur]; } inline void update(int &now, int pre, int l, int r, int p, int v) { now = ++ id; ls[now] = ls[pre]; rs[now] = rs[pre]; miv[now] = min(miv[pre], v); if(l == r) return; int mid = (l + r) >> 1; if(p <= mid) update(ls[now], ls[pre], l, mid, p, v); else update(rs[now], rs[pre], mid + 1, r, p, v); } inline void insert(int &now, int pre, int l, int r, int p, int v) { now = ++ id; ls[now] = ls[pre]; rs[now] = rs[pre]; miv[now] = min(miv[pre], v); if(l == r) return; int mid = (l + r) >> 1; if(p <= mid) insert(ls[now], ls[pre], l, mid, p, v); else insert(rs[now], rs[pre], mid + 1, r, p, v); } inline void build() { int fr = 1, to = 0; q[++ to] = r; miv[0] = 1e9; while(fr <= to) { int o = q[fr]; for(ri i = cap[o]; i; i = nxt[i]) if(cur != fa[o]) q[++ to] = cur; if(dep[o] != dep[q[fr - 1]]) insert(rt[dep[o]], rt[dep[o] - 1], 1, n, dfn[o], w[o]); else update(rt[dep[o]], rt[dep[o]], 1, n, dfn[o], w[o]); fr ++; cmax(mxd, dep[o]); } } inline int qry(int o, int l, int r, int ml, int mr) { if(ml > r || mr < l || !o) return 1e9; if(ml <= l && mr >= r) return miv[o]; int mid = (l + r) >> 1; return min(qry(ls[o], l, mid, ml, mr), qry(rs[o], mid + 1, r, ml, mr)); } int main() { n = read(); r = read(); rep(i, 1, n) w[i] = read(); rep(i, 2, n) { int u = read(), v = read(); addedge(u, v); addedge(v, u); } dfs(r, 0); build(); int lst = 0; m = read(); rep(i, 1, m) { int x = (read() + lst) % n + 1; int k = (read() + lst) % n; write(lst = qry(rt[min(dep[x] + k, mxd)], 1, n, dfn[x], dfn[x] + sz[x] - 1)); } return 0; }

CF893F Subtree Minimum Query 主席樹