线段树(动态开点,合并,区间修改)

#include <iostream> 
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cmath>

using namespace std;
typedef long long ll;

int n, m, root;

struct MergeSegmentTree {
	#define lid lson[id]
	#define rid rson[id]
	int lson[5211314] = {}, rson[5211314] = {}, tot = 0;
	ll sum[5211314] = {}, lazy[5211314] = {}; 
	inline void PushUp(int id) {
		sum[id] = sum[lid] + sum[rid];
		return;
	}
	inline void PushDown(int id, int l, int r) {
		if (lazy[id] != 0) {
			int mid = (l + r) >> 1;
			sum[lid] += (mid - l + 1) * lazy[id];
			sum[rid] += (r - mid) * lazy[id];
			lazy[lid] += lazy[id];
			lazy[rid] += lazy[id];
			lazy[id] = 0;
		}
		return;
	}//下放 
	void UpdatePoint(int &id, int l, int r, int pos, int num) {
		if (id == 0) ++ tot, id = tot;
		if (l == r) {
			sum[id] = num;
			return;
		}
		PushDown(id, l, r);
		int mid = (l + r) >> 1;
		if (pos <= mid) UpdatePoint(lid, l, mid, pos, num);
		else UpdatePoint(rid, mid + 1, r, pos, num);
		PushUp(id);
		return;
	}//单点更新 
	void UpdateInterval(int &id, int l, int r, int vl, int vr, int num) {
		if (id == 0) ++ tot, id = tot;
		if (vl <= l && r <= vr) {
			sum[id] += (r - l + 1) * num;
			lazy[id] += num;
			return;
		}
		PushDown(id, l, r);
		int mid = (l + r) >> 1;
		if (vl <= mid) UpdateInterval(lid, l, mid, vl, vr, num);
		if (mid + 1 <= vr) UpdateInterval(rid, mid + 1, r, vl, vr, num);
		PushUp(id);
		return; 
	}//区间更新 
	ll Query(int &id, int l, int r, int vl, int vr) {
		if (id == 0) ++ tot, id = tot;
		if (vl <= l && r <= vr) {
			return sum[id];
		}
		PushDown(id, l, r);
		int mid = (l + r) >> 1;
		ll ans = 0;
		if (vl <= mid) ans += Query(lid, l, mid, vl, vr);
		if (mid + 1 <= vr) ans += Query(rid, mid + 1, r, vl, vr);
		PushUp(id);
		return ans;
	}//查询 
	int Merge(int a1, int b1, int l, int r) {
		if ((a1 | b1) == 0) return (a1 | b1);
		if (l == r) {
			sum[a1] += sum[b1];
			lazy[a1] += sum[b1];
			return a1;
		}
		int mid = (l + r) >> 1;
		PushDown(a1, l, r), PushDown(b1, l, r);
		lson[a1] = Merge(lson[a1], lson[b1], l, mid);
		rson[a1] = Merge(rson[a1], rson[b1], mid + 1, r);
		PushUp(a1);
		return a1;
	}//合并 
	#undef lid
	#undef rid
}tree; 

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		ll ask;
		scanf("%lld", &ask);
		tree.UpdatePoint(root, 1, n, i, ask);
	}
	for (int i = 1, op, x, y; i <= m; ++ i) {
		ll k;
		scanf("%d", &op);
		if (op == 1) {
			scanf("%d%d%lld", &x, &y, &k);
			tree.UpdateInterval(root, 1, n, x, y, k);
		}
		else {
			scanf("%d%d", &x, &y);
			printf("%lld\n", tree.Query(root, 1, n, x, y));
		}
	}
	return 0;
}
posted @ 2023-07-29 06:26  觉清风  阅读(31)  评论(0编辑  收藏  举报