萌新求助线段树 10pts
查看原帖
萌新求助线段树 10pts
560516
喵仔牛奶楼主2023/3/25 15:10

思路是维护区间最大值 mx,最小值 mn,从左到右走的最大值 ls,从右到左走的最大值 rs

测评记录:https://www.luogu.com.cn/record/105832287

#include <bits/stdc++.h>
using namespace std;
namespace Milkcat {
	typedef long long LL;
	const int N = 1e6 + 5, inf = 1e9;
	LL n, q, rt, mod, opt, u, v, x, a[N];
	struct SegmentTree {
		struct node {
			LL mx, mn, ls, rs;
			node(LL _1 = 0, LL _2 = 0, LL _3 = 0, LL _4 = 0) :
				mx(_1), mn(_2), ls(_3), rs(_4) {}
			node operator *= (int x) { mx += x, mn += x; }
			node operator + (node qwq) {
				node res;
				res.ls = max({ls, qwq.ls, qwq.mx - mn});
				res.rs = max({rs, qwq.rs, mx - qwq.mn});
				res.mx = max(mx, qwq.mx), res.mn = min(mn, qwq.mn);
				return res;
			}
		} sum[N << 1];
	    LL cnt, tag[N << 1], Ls[N << 1], Rs[N << 1];
	    inline int ls(int p) { return Ls[p] ? Ls[p] : Ls[p] = ++ cnt; }
	    inline int rs(int p) { return Rs[p] ? Rs[p] : Rs[p] = ++ cnt; }
	    inline void push_up(int p) { sum[p] = sum[ls(p)] + sum[rs(p)]; }
	    void push_down(int p, int l, int r) {
	        int mid = (l + r) >> 1;
	        tag[ls(p)] += tag[p], sum[ls(p)] *= tag[p];
	        tag[rs(p)] += tag[p], sum[rs(p)] *= tag[p];
	        tag[p] = 0;
	    }
	    void modify(int p, int l, int r, int nl, int nr, LL k) {
	        if (nl <= l && r <= nr) { tag[p] += k, sum[p] *= k; return; }
			push_down(p, l, r);
	        int mid = (l + r) >> 1;
	        if (nl <= mid) modify(ls(p), l, mid, nl, nr, k);
	        if (nr > mid) modify(rs(p), mid + 1, r, nl, nr, k);
	        push_up(p);
		}
	    node query(int p, int l, int r, int nl, int nr) {
	        if (nl <= l && r <= nr) {
	        	return sum[p];
	        }
	        push_down(p, l, r);
	        LL mid = (l + r) >> 1;
	        if (nl <= mid && mid < nr)
				return query(ls(p), l, mid, nl, nr) + query(rs(p), mid + 1, r, nl, nr);
	        if (nl <= mid) return query(ls(p), l, mid, nl, nr);
	        if (nr > mid) return query(rs(p), mid + 1, r, nl, nr);
	    }
	    SegmentTree() { cnt = 1; }
	} Sgt;
	struct TreeDecom {
		LL tot, depth[N], fa[N], siz[N], son[N], top[N], id[N];
		vector<int> G[N];
		void add(int u, int v) {
			G[u].push_back(v), G[v].push_back(u);
		}
		void dfs1(int u, int fat) {
			fa[u] = fat, siz[u] = 1, depth[u] = depth[fa[u]] + 1;
			for (int v : G[u]) {
				if (v == fa[u]) continue;
				dfs1(v, u), siz[u] += siz[v];
				if (!son[u] || siz[v] > siz[son[u]])
					son[u] = v;
			}
		}
		void dfs2(int u, int topf) {
			top[u] = topf, id[u] = ++ tot;
			Sgt.modify(1, 1, n, id[u], id[u], a[u]);
			if (son[u]) dfs2(son[u], topf);
			for (int v : G[u]) {
				if (v == fa[u] || v == son[u]) continue;
				dfs2(v, v);
			}
		}
		void updRange(int u, int v, int k) {
			while (top[u] != top[v]) {
				if (depth[top[u]] < depth[top[v]]) swap(u, v);
				Sgt.modify(1, 1, n, id[top[u]], id[u], k), u = fa[top[u]];
			}
			if (depth[u] > depth[v]) swap(u, v);
			Sgt.modify(1, 1, n, id[u], id[v], k);
		}
		int qRange(int u, int v) {
			SegmentTree::node ans1(-inf, inf, -inf, -inf), ans2 = ans1;
			while (top[u] != top[v]) {
//				cout << u << ' ' << v << '\n';
				if (depth[top[u]] < depth[top[v]])
					ans2 = ans2 + Sgt.query(1, 1, n, id[top[v]], id[v]), v = fa[top[v]]; 
				else ans1 = ans1 + Sgt.query(1, 1, n, id[top[u]], id[u]), u = fa[top[u]]; 
			}
			if (depth[u] < depth[v]) ans1 = ans1 + Sgt.query(1, 1, n, id[u], id[v]);
			else ans2 = ans2 + Sgt.query(1, 1, n, id[v], id[u]);
			return max({ans1.ls, ans2.rs, ans2.mx - ans1.mn});
		}
	} T;
	int main() {
		ios::sync_with_stdio(0);
		cin.tie(0), cout.tie(0);
		cin >> n;
		for (int i = 1; i <= n; i ++) cin >> a[i];
		for (int i = 1; i < n; i ++) cin >> u >> v, T.add(u, v);
		cin >> q, T.dfs1(1, 0), T.dfs2(1, 1);
		for (int i = 1; i <= q; i ++) {
			cin >> u >> v >> x;
			cout<< max(T.qRange(u, v), 0) << '\n';
			T.updRange(u, v, x);
		}
		return 0;
	}
}
int main() {
	return Milkcat::main();
}

2023/3/25 15:10
加载中...