欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++实现线段树(lazy-tag方法)-区间修改,区间查询

程序员文章站 2024-03-20 09:36:58
...

代码如下:

#include <iostream>
using namespace std;
const int N = 10010;
typedef long long LL;
LL input[N];

struct node {
	int l, r;
	LL sum;
	LL add;
} tree[4 * N];

void build(int l, int r, int u) {
	tree[u].l = l;
	tree[u].r = r;
	if (l == r) {
		tree[u].sum = input[l];
		return ;
	}
	int mid = (l + r) >> 1;
	build(l, mid, 2 * u);
	build(mid + 1, r, 2 * u + 1);
	tree[u].sum = tree[2 * u].sum + tree[2 * u + 1].sum;
}

void spread(int u) {
	if (tree[u].add) //当lazy tag不为0时,说明当前区间已经被这个影响所作用,
		//这个区间的所有子区间全都攒着工作没有修改
	{
		tree[2 * u].add += tree[u].add;
		tree[2 * u + 1].add += tree[u].add;
		tree[2 * u].sum += tree[u].add * (tree[2 * u].r - tree[2 * u].l + 1);
		tree[2 * u + 1].sum += tree[u].add * (tree[2 * u + 1].r - tree[2 * u + 1].l + 1);
		tree[u].add = 0;
	}
}

void update(int cl, int cr, int w, int u) {
	if (tree[u].l >= cl && tree[u].r <= cr) {
		tree[u].sum += (LL)w * (tree[u].r - tree[u].l + 1);
		tree[u].add += (LL)w;
		return ;
	}
	spread(u);
	int mid = (tree[u].l + tree[u].r) >> 1;
	if (cl <= mid)
		update(cl, cr, w, 2 * u);
	if (cr > mid)//不能写成(cr >= mid),不然可能会死循环
		update(cl, cr, w, 2 * u + 1);
	tree[u].sum = tree[2 * u].sum + tree[2 * u + 1].sum;
}

LL query(int cl, int cr, int u) {
	if (tree[u].l >= cl && tree[u].r <= cr)
		return tree[u].sum;
	spread(u);
	int mid = (tree[u].l + tree[u].r) >> 1;
	LL ans = 0;
	if (cl <= mid)
		ans += query(cl, cr, 2 * u);
	if (cr > mid)
		ans += query(cl, cr, 2 * u + 1);
//	cout << ans << endl;
	return ans;
}


int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> input[i];
	build(1, n, 1);
	cout << query(3, 6, 1) << endl;//查询区间[3,6]所有元素之和
	update(3, 6, 3, 1);//给区间[3,6]所有元素加上3
	cout << query(3, 6, 1) << endl;//再次查询区间[3,6]所有元素之和
	return 0;
}

测试结果:
C++实现线段树(lazy-tag方法)-区间修改,区间查询