换根+倍增 求调
查看原帖
换根+倍增 求调
637796
Xy_top楼主2024/11/24 16:11
#include <bits/stdc++.h>
#define int long long
#define For(i, a, b) for (int i = (a); i <= (b); i ++)
#define foR(i, a, b) for (int i = (a); i >= (b); i --)
using namespace std;
int n, q;
int dp[400005], f[200005], f2[200005], fa[200005][18], mx[200005][18];
int dep[200005], sum[200005];
int c[200005], u[400005], v[400005], w[400005], pre[400005], suf[400005];
struct Edge {int u, v, w;}a[400005];
vector <int> G[200005];
void dfs (int u) {
	f[u] = c[u];
	if (G[u].size () == 1 && G[u][0] == fa[u][0]) return;
	for (int p : G[u]) {
		if (a[p].v == fa[u][0]) continue;
		fa[a[p].v][0] = u;
		sum[a[p].v] = sum[u] + a[p].w;
		dep[a[p].v] = dep[u] + 1;
		dfs (a[p].v);
		dp[p] = f[a[p].v] - 2 * a[p].w;
		f[u] = max (f[u], dp[p]);
	}
}
void redfs (int u) {//求点 u 走父亲的答案,到这个点时,该点走父亲的答案已有
	if (a[G[u][0] ].v == fa[u][0]) pre[0] = -100000000000000000LL;
	else pre[0] = dp[G[u][0] ];
	For (i, 1, G[u].size () - 1) {
		if (a[G[u][i] ].v == fa[u][0]) pre[i] = pre[i - 1];
		else pre[i] = max (pre[i - 1], dp[G[u][i] ]);
	}
	suf[G[u].size ()] = -100000000000000000LL;
	foR (i, G[u].size () - 1, 0) {
		if (a[G[u][i] ].v == fa[u][0]) suf[i] = suf[i + 1];
		else suf[i] = max (suf[i + 1], dp[G[u][i] ]);
	}
	For (i, 0, G[u].size () - 1) {
		if (a[G[u][i] ].v == fa[u][0]) continue;
		int val = -100000000000000000LL;
		if (i == 0) val = suf[i + 1];
		else val = max (pre[i - 1], suf[i + 1]);
		f2[a[G[u][i] ].v] = max (f2[u], val) - 2 * a[G[u][i] ].w;
		redfs (a[G[u][i] ].v);
	}
}
int lca (int x, int y) {
	if (dep[x] < dep[y]) swap (x, y);
	foR (i, 17, 0) if (dep[fa[x][i] ] >= dep[y]) x = fa[x][i];
	if (x == y) return x;
	foR (i, 17, 0) if (fa[x][i] != fa[y][i]) {
		x = fa[x][i];
		y = fa[y][i];
	}
	return fa[x][0];
}
int query (int x, int y) {//查询 x 到 y 路径上 dp 最大值
	int ret = -100000000000000000LL;
	foR (i, 17, 0) if (dep[fa[x][i] ] >= dep[y]) {
		ret = max (ret, mx[x][i]);
		x = fa[x][i];
	}
	return max (ret, mx[y][0]);
}
void solve () {
	dep[1] = 1;
	cin >> n >> q;
	For (i, 1, n) cin >> c[i];
	For (i, 1, n - 1) {
		int x, y, z;
		cin >> x >> y >> z;
		a[2 * i] = {x, y, z};
		a[2 * i + 1] = {y, x, z};
		G[x].push_back (2 * i);
		G[y].push_back (2 * i + 1);
	}
	dfs (1);
	f2[1] = -100000000000000000LL;
	redfs (1);
	For (i, 1, n) For (j, 1, 17) fa[i][j] = fa[fa[i][j - 1] ][j - 1];
	For (i, 1, n) mx[i][0] = f[i];
	For (i, 1, n) For (j, 1, 17) mx[i][j] = max (mx[i][j - 1], mx[fa[i][j - 1] ][j - 1]);
	while (q --) {
		int x, y;
		cin >> x >> y;
		int l = lca (x, y);
		cout << c[x] + c[y] - (sum[x] + sum[y] - 2 * sum[l]) + max ({query (x, l), query (y, l), f2[l]}) << '\n';
	}
}
signed main () {
	int _ = 1;
	while (_ --) {
		solve ();
		cout << '\n';
	}
	return 0;
}
2024/11/24 16:11
加载中...