1. 程式人生 > >poj3468(線段樹區間查詢+區間更新)

poj3468(線段樹區間查詢+區間更新)

思路:很明顯的線段樹模板題,區間查詢+區間更新

但是小弟比較菜,並不會線段樹,所以現學了一波,別的還是好理解的,就是lazy標記我覺得很難理解(應該是因為我比較菜),所以請教了大佬,大佬告訴我:lazy標記就是在訪問這個節點時,並且要訪問子節點時,向下傳遞lazy標記,以減少時間;訪問操作包含了(查詢與更新);

程式碼如下:

#include<cstdio>
#include<algorithm>
using namespace std;
/*
poj3468 線段樹區間更新,區間查詢
坑點:資料會超過int
*/
struct SegTree
{
	int l, r;//區間端點 
	long long  val;//區間值 
	long long lazy;//當訪問到這個節點並且要訪問子節點的時候,向下傳遞標記
			//訪問包括了更新跟查詢操作 
}segtree[410000];
void pushup(int root)//更新父節點 
{
	segtree[root].val = segtree[root << 1].val + segtree[root << 1 | 1].val;
}
void pushdown(int root)
{
	segtree[root << 1].lazy += segtree[root].lazy;
	segtree[root << 1 | 1].lazy += segtree[root].lazy;
	segtree[root << 1].val += (segtree[root << 1].r - segtree[root << 1].l + 1)*segtree[root].lazy;
	segtree[root << 1 | 1].val += (segtree[root << 1 | 1].r - segtree[root << 1 | 1].l + 1)*segtree[root].lazy;
	segtree[root].lazy = 0;

}
void build(int root, int left, int right)
{
	segtree[root].l = left;
	segtree[root].r = right;
	if (left == right)
	{
		scanf("%lld", &segtree[root].val);
		return;
	}
	int mid = (left + right) >> 1;
	build(root << 1, left, mid);//建左子樹
	build(root << 1 | 1, mid + 1, right);//建右子樹
	pushup(root);//根據左右子樹確定父節點 
}
long long query(int root, int qleft, int qright)
{
	if (qleft <= segtree[root].l&&qright >= segtree[root].r)
	{
		return segtree[root].val;
	}
	pushdown(root);
	long long ans = 0;
	int mid = (segtree[root].l + segtree[root].r) >> 1;
	if (qleft <= mid)
	{
		ans += query(root << 1, qleft, qright);
	}
	if (qright > mid)
	{
		ans += query(root << 1 | 1, qleft, qright);
	}
	return ans;
}
void add(int root, int qleft, int qright, long long val)
{
	if (qleft <= segtree[root].l&&qright >= segtree[root].r)//如果當前區間在所求區間中 
	{
		segtree[root].val += (segtree[root].r - segtree[root].l + 1)*val;
		segtree[root].lazy += val;
		return;
	}
	pushdown(root);
	int mid = (segtree[root].l + segtree[root].r) >> 1;
	if (qleft <= mid)
	{
		add(root << 1, qleft, qright, val);
	}
	if (qright > mid)
	{
		add(root << 1 | 1, qleft, qright, val);
	}
	pushup(root);
}
int main()
{
	int n, m;
	char op[10];
	scanf("%d%d", &n, &m);
	build(1, 1, n);
	while (m--)
	{
		scanf("%s", op);
		if (op[0] == 'Q')//查詢 
		{
			int a, b;
			scanf("%d%d", &a, &b);
			printf("%lld\n", query(1, a, b));
		}
		else if (op[0] == 'C')
		{
			int a, b, val;
			scanf("%d%d%d", &a, &b, &val);
			add(1, a, b, val);
		}
	}
	//system("pause");
	return 0;
}
/*
10 1000
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

*/