21.11.16模拟 bzoj3306树

要求修改树上点权,查询子树内最小值和换根

对于换根操作,我们不妨分类讨论一下
设初始的根为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;
}

本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15566277.html

原文地址:https://www.cnblogs.com/QQ2519/p/15566277.html