要求修改树上点权,查询子树内最小值和换根
对于换根操作,我们不妨分类讨论一下
设初始的根为1,当前的根为rt,要查询的子树x
若x==rt,直接输出全局最小值即可
在以1为根的情况下
若rt是x的祖先,那么当前的最小值还是在x的子树内
若x是rt的祖先,那么x原本的子树中到rt的子树就不能要了。在倍增求LCA(rt,x)的时候,求出lca,顺便求出rt,x中距离x最近的节点y,把y的子树删去,就是目前的答案
const int N = 1e5 + 79;
struct graph {
int head[N], tot, next[N << 1], ver[N << 1];
inline void add(int a, int b) {
ver[++tot] = b;
next[tot] = head[a];
head[a] = tot;
}
} G;
int n, Q;
int a[N], b[N], rt;
int dfn[N], siz[N], tim;
int anc[20][N], dep[N];
inline void dfs(int x) {
dep[x] = dep[anc[0][x]] + 1;
dfn[x] = ++tim;
b[tim] = a[x];
siz[x] = 1;
rep(i, 1, 18) {
anc[i][x] = anc[i - 1][anc[i - 1][x]];
}
repg(x) {
int y(G.ver[i]);
if(y == anc[0][x]) continue;
anc[0][y] = x;
dfs(y);
siz[x] += siz[y];
}
}
struct SgementTree {
int lc[N << 2], rc[N << 2];
int mi[N << 2], rt, cnt;
inline void build(int &p, int L, int R) {
if(!p) p = ++cnt;
if(L == R) {
mi[p] = b[L];
return ;
}
int mid(L + R >> 1);
build(lc[p], L, mid);
build(rc[p], mid + 1, R);
mi[p] = min(mi[lc[p]], mi[rc[p]]);
}
inline void change(int &p, int L, int R, int pos, int val) {
if(!p) p = ++cnt;
if(L == R) {
mi[p] = val;
return ;
}
int mid(L + R >> 1);
if(pos <= mid) change(lc[p], L, mid, pos, val);
else change(rc[p], mid + 1, R, pos, val);
mi[p] = min(mi[lc[p]], mi[rc[p]]);
}
inline int query(int &p, int L, int R, int ll, int rr) {
if(!p) return 0;
if(ll <= L && rr >= R) {
return mi[p];
}
int mid(L + R >> 1), ans(1e9);
if(ll <= mid)ans = min(ans, query(lc[p], L, mid, ll, rr));
if(rr > mid) ans = min(ans, query(rc[p], mid + 1, R, ll, rr));
return ans;
}
} S;
#define pii std::pair<int,int>
inline pii lca(int x, int y) {
if(dep[x] < dep[y]) std::swap(x, y);
drp(i, 18, 0) {
if(dep[anc[i][x]] > dep[y]) {
x = anc[i][x];
}
}
if(anc[0][x] == y) return {anc[0][x], x};
drp(i, 18, 0) {
if(anc[i][x]^anc[i][y]) {
x = anc[i][x];
y = anc[i][y];
}
}
return {anc[0][x], x};
}
int main() {
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
read(n);
read(Q);
int f;
rep(i, 1, n) {
read(f);
read(a[i]);
if(!f) {
rt = i;
}
G.add(f, i);
G.add(i, f);
}
dfs(rt);
S.build(S.rt, 1, n);
char op;
int x, y;
while(Q--) {
while( (op = gt()) != 'E' && op != 'V' && op != 'Q');
read(x);
if(op == 'V') {
read(y);
S.change(S.rt, 1, n, dfn[x], y);
} else if(op == 'E') {
rt = x;
} else {
if(rt == x) {
out(S.mi[S.rt], '\n');
continue;
}
pii s = lca(rt, x);
if(s.first != x) {
out(S.query(S.rt, 1, n, dfn[x], dfn[x] + siz[x] - 1), '\n');
} else {
out(min(S.query(S.rt, 1, n, 1, dfn[s.second] - 1), S.query(S.rt, 1, n, dfn[s.second] + siz[s.second] + 1, n)), '\n');
}
}
}
return 0;
}