线段树基础理论篇

53 阅读1分钟

线段树 从入门到进阶(超清晰,简单易懂)_进阶线段树-CSDN博客

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int a[N];
int ans;

struct segment_tree {
	struct node {
		int l, r, num;
	} tr[N * 4];

	void build(int p, int l, int r) {
		tr[p] = {l, r, 0};
		if (l == r) {
			tr[p].num = a[l];
			return;
		}
		int mid = l + r >> 1;
		build(p << 1, l, mid); //实际上就是p*2  左子树
		build(p << 1 | 1, mid + 1, r); //实际上就是p*2+1  右子树
	}

	void modify(int p, int l, int r, int k) {
		//如果当前区间被目标区间覆盖了就直接输出其区间和
		if (tr[p].l >= l && tr[p].r <= r) {
			tr[p].num += k;
			return;
		}
		int mid = tr[p].l + tr[p].r >> 1;
		if (l <= mid)
			modify(p << 1, l, r, k); //如果当前区间和目标区间的左孩子区间有交集,就搜索左区间
		if (r > mid)
			modify(p << 1 | 1, l, r, k);
	}

	void query(int p, int x) {
		ans += tr[p].num;
		if (tr[p].l == tr[p].r)
			return;

		int mid = tr[p].l + tr[p].r >> 1;
		if (x <= mid)
			query(p << 1, x);
		else
			query(p << 1 | 1, x);
	}
} st;

int main() {
	cin.tie(nullptr)->sync_with_stdio(false);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i];

	//建树
	st.build(1, 1, n);
	for (int i = 1; i <= m; i++) {
		int c;
		cin >> c;
		if (c == 1) {
			int x, y, k;
			cin >> x >> y >> k;
			st.modify(1, x, y, k);
		} else {
			ans = 0;
			int x;
			cin >> x;
			st.query(1, x);
			printf("%d\n", ans);
		}
	}
	return 0;
}