重剖30pts求条
查看原帖
重剖30pts求条
921417
crean_楼主2024/10/30 14:33

AC on #5 #6 #9

#include<bits/stdc++.h>
using namespace std;
int siz[400005];//子树大小
int hson[400005];//重儿子
long long a[400005];
int deep[400005];
int rak[400005];//这个dfn值对应的编号
int dfn[400005];//这个点的dfn值
int top[400005];//这点所在的链的链顶
int vis[400005];
long long seg[400005];//线段树
long long maxx[400005];
int fa[400005];
vector<int> g[30005];
int n, m;
int dfs(int pos) {
	hson[pos] = 0;
	siz[pos] = 1;
	for (auto x : g[pos]) {
		if (!deep[x]) {
			fa[x] = pos;
			deep[x] = deep[pos] + 1;
			siz[pos] += dfs(x);
			if (siz[x] > siz[hson[pos]]) {
				hson[pos] = x;
			}
		}
	}
	return siz[pos];
}
int cnt;
void dfs2(int t, int pos) {
	top[pos] = t;
	dfn[++cnt] = pos;
	rak[pos] = cnt;
	if (g[pos].size() == 0) return;//叶子节点没有儿子,直接返回
	if (hson[pos] != 0) {
		vis[hson[pos]] = 1;
		dfs2(t, hson[pos]);
	}
	for (auto x : g[pos]) {
		if (!vis[x]) {
			vis[x] = 1;
			dfs2(x, x);
		}
	}
}
void upd(int x) {
	seg[x] = seg[x * 2] + seg[x * 2 + 1];
	maxx[x] = max(maxx[x * 2], maxx[x * 2 + 1]);
}
void bt(int l, int r, int pos) {
	if (l == r) {
		seg[pos] = a[dfn[l]];
		maxx[pos] = a[dfn[l]];
		return;
	}
	int mid = (l + r) >> 1;
	bt(l, mid, pos * 2);
	bt(mid + 1, r, pos * 2 + 1);
	upd(pos);
}
void modi(int x, int L, int R, int pos, long long val) {
	if (L == R) {
		seg[pos] = val;
		maxx[pos] = val;
		return;
	}
	int mid = (L + R) >> 1;
	if (x > mid) modi(x, mid + 1, R, pos * 2 + 1, val);
	else modi(x, L, mid, pos * 2, val);
	upd(pos);
}
long long qsum(int l, int r, int L, int R, int pos) {
	if (l <= L && r >= R) {
		return seg[pos];
	} else if (l > R || r < L) return 0;
	int mid = (L + R) >> 1;
	return qsum(l, r, L, mid, pos * 2) + qsum(l, r, mid + 1, R, pos * 2 + 1);
}
long long maxsum(int l, int r, int L, int R, int pos) {
	if (l <= L && r >= R) {
		return maxx[pos];
	} else if (l > R || r < L) return LLONG_MIN; // 极小值
	int mid = (L + R) >> 1;
	return max(maxsum(l, r, L, mid, pos * 2), maxsum(l, r, mid + 1, R, pos * 2 + 1));
}
long long squel(int x, int y) {
	long long ans = 0;
	int fx = top[x], fy = top[y];
	while (fx != fy) {
		if (deep[fx] >= deep[fy]) {//fx深就把x跳到链顶
			ans += qsum(dfn[fx], dfn[x], 1, n, 1);
			x = fa[fx];
		} else {//不然跳y
			ans += qsum(dfn[fy], dfn[y], 1, n, 1);
			y = fa[fy];
		}
		fx = top[x];
		fy = top[y];
	}
	if (deep[x] >= deep[y]) {
		ans += qsum(dfn[y], dfn[x], 1, n, 1);
	} else {
		ans += qsum(dfn[x], dfn[y], 1, n, 1);
	}
	return ans;
}
long long mquel(int x, int y) {
	long long ans = LLONG_MIN;
	int fx = top[x], fy = top[y];
	while (fx != fy) {
		if (deep[fx] >= deep[fy]) {//fx深就把x跳到链顶
			ans = max(maxsum(dfn[fx], dfn[x], 1, n, 1), ans);
			x = fa[fx];
		} else {
			ans = max(maxsum(dfn[fy], dfn[y], 1, n, 1), ans);
			y = fa[fy];
		}
		fx = top[x];
		fy = top[y];
	}
	if (deep[x] >= deep[y]) {
		ans = max(maxsum(dfn[y], dfn[x], 1, n, 1), ans);
	} else {
		ans = max(maxsum(dfn[x], dfn[y], 1, n, 1), ans);
	}
	return ans;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin >> n;
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	cin >> m;
	deep[1] = 1;
	fa[1] = 1;
	dfs(1);
	vis[1] = 1;
	dfs2(1, 1);
	bt(1, cnt, 1);
	for (int i = 1; i <= m; i++) {
		string op;
		int x, y;
		cin >> op >> x >> y;
		if (op == "QMAX") {
			cout << mquel(x, y) << endl;
		} else if (op == "QSUM") {
			cout << squel(x, y) << endl;
		} else if (op == "CHANGE") {
			modi(dfn[x], 1, cnt, 1, y);
		}
	}
}
2024/10/30 14:33
加载中...