线段树区间更新、区间查询模板

#include "iostream"
#include "cstdio"
#include "cstdlib"
#include "cstring"
#include "cmath"
#include "algorithm"
#include "queue"
#include "vector"
#include "stack"
#include "map"
#include "set"
#include "climits"
using namespace std;
typedef long long ll;
typedef unsigned long long LL;
const int maxn = 100010;
const int INF = 0x3f3f3f3f;

ll tree[maxn << 2], lazy[maxn << 2], A[maxn];
int n, m;

void push_down(int node, int start, int end) {
	if(lazy[node]) {
		lazy[node << 1] += lazy[node];
		lazy[node << 1 | 1] += lazy[node];
		int mid = (start + end) >> 1;
		tree[node << 1] += (mid - start + 1) * lazy[node];
		tree[node << 1 | 1] += (end - mid) * lazy[node];
		lazy[node] = 0;
	}
}

void build(int node, int start, int end) {
	if(start == end) {
		tree[node] = A[start];
		return ;
	}
	int mid = (start + end) >> 1;
	build(node << 1, start, mid);
	build(node << 1 | 1, mid + 1, end);
	tree[node] = tree[node << 1] + tree[node << 1 | 1];
}

void update(int node, int start, int end, int L, int R, ll val) {
	if(L <= start && R >= end) {
		tree[node] += (end - start + 1) * val;
		lazy[node] += val;
		return ;
	}
	push_down(node, start, end);
	int mid = (start + end) >> 1;
	if(L <= mid) update(node << 1, start, mid, L, R, val);
	if(R > mid) update(node << 1 | 1, mid + 1, end, L, R, val);
	tree[node] = tree[node << 1] + tree[node << 1 | 1];
}

ll query(int node, int start, int end, int L, int R) {
	if(L <= start && R >= end) return tree[node];
	push_down(node, start, end);
	ll ans = 0;
	int mid = (start + end) >> 1;
	if(L <= mid) ans += query(node << 1, start, mid, L, R);
	if(R > mid) ans += query(node << 1 | 1, mid + 1, end, L, R);
	return ans;
}

void Segment_Tree() {
	cin >> n >> m;
	for(int i = 1; i <= n; ++i) cin >> A[i];
	build(1, 1, n);
	for(int i = 0; i < m; ++i) {
		int t;
		cin >> t;
		if(t == 1) {
			ll l, r, val;
			cin >> l >> r >> val;
			update(1, 1, n, l, r, val);
		}else {
			ll l, r;
			cin >> l >> r;
			cout << query(1, 1, n, l, r) << endl;
		}
	}
}

int main() {
	Segment_Tree();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值