妺子刚学oi, 简单树剖求调
查看原帖
妺子刚学oi, 简单树剖求调
527992
kaceqwq楼主2023/1/9 19:32
#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int N = 2000005;
int n, m, a[N], tot, cnt, head[N];
struct Node{
	int Lmax, Rmax, Smax, sum, add;
	bool flag;
	Node() {Lmax = Rmax = Smax = sum = 0;}
}Tree[N];
struct jc{
	int size, fa, d, hson, seg, rev, top;
}E[N];
struct T{
	int to, net;
}e[N];
void add(int x, int y) {
	e[++tot].to = y;
	e[tot].net = head[x];
	head[x] = tot;
}
void dfs1(int x, int F) {
	E[x].fa = F, E[x].size = 1, E[x].d = E[F].d + 1;
	for (int i = head[x]; i; i = e[i].net) {
		int y = e[i].to;
		if (y == F) continue;
		dfs1(y, x);
		E[x].size += E[y].size;
		if (E[y].size > E[E[x].hson].size) E[x].hson = y;
	}
}
void dfs2(int x, int Top) {
	E[x].top = Top, E[x].seg = ++cnt, E[cnt].rev = x;
	if (E[x].hson) dfs2(E[x].hson, Top);
	for (int i = head[x]; i; i = e[i].net) {
		int y = e[i].to;
		if (!E[y].top) dfs2(y, y);
	}
}
Node Push_up (Node l, Node r) {
	Node ans;
	ans.sum = l.sum + r.sum;
	ans.Lmax = max(l.Lmax, l.sum + r.Lmax);
	ans.Rmax = max(r.Rmax, r.sum + l.Rmax);
	ans.Smax = max(l.Rmax + r.Lmax, max(l.Smax, r.Smax));
	ans.add = ans.flag = 0;
	return ans;
}
void Build (int p, int l, int r) {
	if(l == r) {
		Tree[p].sum = a[E[l].rev];
		Tree[p].Lmax = Tree[p].Rmax = Tree[p].Smax = max(Tree[p].sum, (int)0);
		Tree[p].flag = 0;
		return ;
	}
	int mid = (l + r) >> 1;
	Build(p * 2, l, mid);
	Build(p * 2 + 1, mid + 1, r);
	Tree[p] = Push_up(Tree[p * 2], Tree[p * 2 + 1]);
}
void Push_down(int p, int l, int r) {
	if(!Tree[p].add) return ;
	int mid = (l + r) / 2;
	Tree[p * 2].add = Tree[p].add;
	Tree[p * 2 + 1].add = Tree[p].add;
	Tree[p * 2].sum = Tree[p].add * (mid - l + 1);
	Tree[p * 2 + 1].sum = Tree[p].add * (r - mid);
	Tree[p * 2].flag = Tree[p * 2 + 1].flag = 1;
	Tree[p * 2].Lmax = Tree[p * 2].Rmax = Tree[p * 2].Smax = max (Tree[p * 2].sum, (int)0);
	Tree[p * 2 + 1].Lmax = Tree[p * 2 + 1].Rmax = Tree[p * 2 + 1].Smax = max (Tree[p * 2 + 1].sum, (int)0);
	Tree[p].add = Tree[p].flag = 0;
}
void Change(int p, int l, int r, int L, int R, int k) {
	if (l > R || r < L) return ;
	if (l >= L && r <= R) {
		Tree[p].sum = k * (r - l + 1);
		Tree[p].Lmax = Tree[p].Rmax = Tree[p].Smax = max(Tree[p].sum, (int)0);
		Tree[p].flag = 1;
		Tree[p].add = k;
		return ;
	}
	Push_down(p, l, r);
	int mid = (l + r) / 2;
	if (L <= mid) Change(p * 2, l, mid, L, R, k);
	if (R > mid) Change(p * 2 + 1, mid + 1, r, L, R, k);
	Tree[p] = Push_up(Tree[p * 2], Tree[p * 2 + 1]);
}
Node Query(int p, int l, int r, int L, int R) {
	if(l <= L && R <= r) return Tree[p];
	Push_down(p, l, r);
	int mid = (l + r) / 2;
	Node ll, rr;
	if(L <= mid) ll = Query(p * 2, l, mid, L, R);
	if(R > mid) rr = Query(p * 2 + 1, mid + 1, r, L, R);
	return Push_up(ll, rr);
}
void iChange(int x, int y, int val) {
	int topx = E[x].top, topy = E[y].top;
	while(topx != topy) {
		if (E[topx].d < E[topy].d) {
			swap(x, y);
			swap(topx, topy);
		}
		Change(1, 1, cnt, E[topx].seg, E[x].seg, val);
		x = E[topx].fa;
		topx = E[x].top;
	}
	if (E[x].d > E[y].d) swap(x, y);
	Change(1, 1, cnt, E[x].seg, E[y].seg, val);
}
Node iQuery(int x, int y) {
	int topx = E[x].top, topy = E[y].top;
	Node L, R;
	while(topx != topy) {
		if (E[topx].d < E[topy].d) {
			R = Push_up(Query(1, 1, cnt, E[topx].seg, E[y].seg), R);
			y = E[topy].fa;
			topy = E[y].top;
		}
		else {
			L = Push_up(Query(1, 1, cnt, E[topx].seg, E[x].seg), L);
			x = E[topx].fa;
			topx = E[x].top;
		}
	}
	if (E[x].d > E[y].d) L = Push_up(Query(1, 1, cnt, E[y].seg, E[x].seg), L);
	else R = Push_up(Query(1, 1, cnt, E[x].seg, E[y].seg), R);
	swap(L.Lmax, R.Rmax);
	return Push_up(L, R);
}
signed main() {
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i < n; i++) {
		int x, y;
		cin >> x >> y;
		add(x, y);
		add(y, x);
	}
	dfs1(1, 0);
	dfs2(1, 1);
	Build(1, 1, cnt);
	cin >> m;
	while (m--) {
		int op, x, y, z;
		cin >> op >> x >> y;
		if (op == 1) {
			cout << iQuery(x, y).Smax << '\n';
		}
		else {
			cin >> z;
			iChange(x, y, z);
		}
	}
	return 0;
}
2023/1/9 19:32
加载中...