思路:很明显的线段树模板题,区间查询+区间更新
但是小弟比较菜,并不会线段树,所以现学了一波,别的还是好理解的,就是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
*/