社区讨论

玄关求调感激不尽

P4719【模板】动态 DP参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mjk3q8el
此快照首次捕获于
2025/12/24 22:21
2 个月前
此快照最后确认于
2025/12/27 11:00
2 个月前
查看原帖
蒟蒻第一次写 ddp,求调谢谢!
CPP
#include <iostream>
#include <vector>
#include <algorithm>
#define int long long
#define inf 1e12
#define debug(x) cerr << #x << ": " << x << endl
using namespace std;

const int MAXN = 1e6 + 7;
int a[MAXN], son[MAXN], siz[MAXN], fat[MAXN], dfn[MAXN], ant[MAXN], top[MAXN], down[MAXN], f[MAXN][2], g[MAXN][2], dfcnt, n, m;
vector<int> to[MAXN];

void init(int idx, int fa = 0) {
	siz[idx] = 1;
	fat[idx] = fa;
	f[idx][1] = a[idx];
	for (int i : to[idx]) {
		if (i == fa) continue;
		init(i, idx);
		f[idx][0] += max(f[i][0], f[i][1]);
		f[idx][1] += f[i][0];
		siz[idx] += siz[i];
		if (siz[i] > siz[son[idx]])
			son[idx] = i;
	}
}

void dfs(int idx) {
	dfn[idx] = ++dfcnt; ant[dfcnt] = idx;
	g[idx][1] = a[idx];
	if (son[idx]) top[son[idx]] = top[idx], dfs(son[idx]), down[idx] = down[son[idx]];
	else down[idx] = idx;
	for (int i : to[idx]) {
		if (i == fat[idx] || i == son[idx]) continue; ///////////
		g[idx][0] += max(f[i][0], f[i][1]);
		g[idx][1] += f[i][0];
		top[i] = i;
		dfs(i);
	}
}

struct matrix
{
	int val[2][2]{};
	int* operator[](int x) { return val[x]; }
	void dbg() { for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) cout << val[i][j] << ' '; cout << endl; }
};

matrix operator* (matrix u, matrix v)
{
	matrix ret;
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 2; j++)
			for (int k = 0; k < 2; k++)
				ret[i][j] = max(ret[i][j], u[i][k] + v[k][j]);
	return ret;
}

matrix id() { matrix I; I[0][1] = I[1][0] = -inf; return I; }

#define lsx (2 * idx)
#define rsx (2 * idx)
#define mid (l + r >> 1)
struct segtree
{
	matrix tree[MAXN];
	void pushup(int idx) { tree[idx] = tree[lsx] * tree[rsx]; }
	void build(int l = 1, int r = n, int idx = 1) {
		if (l == r) {
			tree[idx][0][0] = tree[idx][0][1] = g[ant[l]][0];
			tree[idx][1][0] = g[ant[l]][1]; tree[idx][1][1] = -inf;
			return;
		}
		build(l, mid, lsx);
		build(mid + 1, r, rsx);
		pushup(idx);
	}
	void add(int qidx, int val, int x, int y, int l = 1, int r = n, int idx = 1) {
		if (l == r) {
			tree[idx][x][y] += val;
			return;
		}
		if (qidx <= mid) add(qidx, val, x, y, l, mid, lsx);
		else add(qidx, val, x, y, mid + 1, r, rsx);
		pushup(idx);
	}
	matrix query(int ql, int qr, int l = 1, int r = n, int idx = 1) {
		if (ql <= l && r <= qr) return tree[idx];
		if (r < ql || qr < l) return id();
		return query(ql, qr, l, mid, lsx) * query(ql, qr, mid + 1, r, rsx);
	}
} tr;

matrix query(int idx) {
	//cout << "Querying: " << idx << ' ' << dfn[idx] << ' ' << dfn[down[idx]] << endl;
	return tr.query(dfn[idx], dfn[down[idx]]);
}

void change(int idx, int val) {
	int mem = idx;
	while (idx) {
		idx = top[idx];
		matrix val = query(idx);
		f[idx][0] = val[0][0];
		f[idx][1] = val[1][0];
		idx = fat[idx];
	}
	//debug("Memorized!");
	idx = mem;
	tr.add(dfn[idx], -a[idx], 1, 0);
	a[idx] = val;
	tr.add(dfn[idx], a[idx], 1, 0);
	while (idx) {
		idx = top[idx];
		matrix newval = query(idx);
		tr.add(dfn[fat[idx]], newval[0][0] - f[idx][0], 1, 0);
		tr.add(dfn[fat[idx]], max(newval[0][0], newval[1][0]) - max(f[idx][0], f[idx][1]), 0, 0);
		tr.add(dfn[fat[idx]], max(newval[0][0], newval[1][0]) - max(f[idx][0], f[idx][1]), 0, 1);
		idx = fat[idx];
	}
}

signed main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i < n; i++) {
		int u, v; cin >> u >> v;
		to[u].push_back(v);
		to[v].push_back(u);
	}
	init(1); top[1] = 1; dfs(1); tr.build();
	//cout << query(1)[0][0] << endl;
	while (m--) {
		int x, y; cin >> x >> y;
		change(x, y);
		matrix ret = query(1);
		cout << max(ret[0][0], ret[1][0]) << '\n';
	}
}

回复

0 条回复,欢迎继续交流。

正在加载回复...