線段樹模板重製(自寫自用)

Ke_scholar發表於2024-08-03
template<class Node>
struct SegmentTree {
#define lc u<<1
#define rc u<<1|1
	const int n, N;
	vector<Node> tr;

	SegmentTree(): n(0) {}
	SegmentTree(int n_): n(n_), N(n * 4 + 10) {
		tr.reserve(N);
		tr.resize(N);
	}
	SegmentTree(vector<int> init) : SegmentTree(init.size()) {
		function<void(int, int, int)> build = [&](int u, int l, int r) {
			tr[u].l = l, tr[u].r = r;
			init_lazy(tr[u]);
			if (l == r) {
				tr[u] = {l, r, 0, init[l], init[l], 1, 1};
				return ;
			}
			i64 mid = (l + r) >> 1;
			build(lc, l, mid);
			build(rc, mid + 1, r);
			pushup(tr[u], tr[lc], tr[rc]);
		};
		build(1, 1, n);
	}

	void cal_lazy(Node & fa, Node & ch) {
		i64 b = fa.add;
		ch.Max += b;
		ch.Min += b;
	}

	void tag_union(Node& fa, Node& ch) {
		i64 b = fa.add;
		ch.add += b;
	}

	void init_lazy(Node& u) {
		u.add = 0;
	}

	void pushdown(i64 u) {
		if (tr[u].add != 0) {
			cal_lazy(tr[u], tr[lc]);
			cal_lazy(tr[u], tr[rc]);
			tag_union(tr[u], tr[lc]);
			tag_union(tr[u], tr[rc]);
			init_lazy(tr[u]);
		}
	}

	void pushup(Node& U, Node& L, Node& R) { //上傳
		U.Max = max(L.Max, R.Max);
		U.Min = min(L.Min, R.Min);

		if (L.Max < R.Min && L.up && R.up) {
			U.up = 1;
		} else {
			U.up = 0;
		}

		if (L.Min > R.Max && L.down && R.down) {
			U.down = 1;
		} else {
			U.down = 0;
		}

	}

	void modify(int u, int l, int r, int k) {
		if (tr[u].l >= l && tr[u].r <= r) {
			tr[u].add += k;
			tr[u].Max += k;
			tr[u].Min += k;
			return ;
		}
		pushdown(u);
		int mid = (tr[u].l + tr[u].r) >> 1;
		if (l <= mid)
			modify(lc, l, r, k);
		if (r > mid)
			modify(rc, l, r, k);
		pushup(tr[u], tr[lc], tr[rc]);
	}

	Node query(int u, int l, int r) { //區查
		if (l <= tr[u].l && tr[u].r <= r)
			return tr[u];
		i64 mid = tr[u].l + tr[u].r >> 1;
		pushdown(u);
		i64 res = LLONG_MIN >> 1;
		if (r <= mid)
			return query(lc, l, r);
		if (l > mid)
			return query(rc, l, r);
		Node U;
		Node L = query(lc, l, r), R = query(rc, l, r);
		pushup(U, L, R);
		return U;
	}
};

struct Node { //線段樹定義
	i64 l, r, add;
	i64 Max, Min;
	bool up, down;
};

相關文章