题目链接在这里
题目描述:
有n个数m个操作,操作有两种:
1.Q x y 查询区间[x, y]的和
2.C x y z 区间[x, y]中的每个元素增加z
思路分析:
运用线段树维护点的信息,在区间更新的时候lazy思想在节点上mark一下。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
#define rl (rt << 1)
#define rr (rt << 1 | 1)
#define clr(x) memset(x, 0, sizeof(x))
#define rep(i, x) for(int i = 0; i < x; ++i)
using namespace std;
const int MaxN = 1e5 + 5;
struct Node{
int l, r, m;
ll sum, mark;
}tree[MaxN << 2];
int a[MaxN];
int n, m;
void build(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
tree[rt].m = (l + r) >> 1;
if(l == r){
tree[rt].sum = a[l];
return;
}
build(l, tree[rt].m, rl);
build(tree[rt].m + 1, r, rr);
tree[rt].sum = tree[rl].sum + tree[rr].sum;
}
void update(int l, int r, int rt, int val){
if(tree[rt].l == l && tree[rt].r == r){
tree[rt].mark += val;
return;
}
tree[rt].sum += val * (r - l + 1);
if(r <= tree[rt].m)
update(l, r, rl, val);
else if(l > tree[rt].m)
update(l, r, rr, val);
else{
update(l, tree[rt].m, rl, val);
update(tree[rt].m + 1, r, rr, val);
}
}
ll query(int l, int r, int rt){
//printf("l:%d, r:%d\n", l, r);
//printf("rt, l:%d, r:%d\n", tree[rt].l, tree[rt].r);
if(l == tree[rt].l && r == tree[rt].r){
return tree[rt].sum + tree[rt].mark * (r - l + 1);
}
if(tree[rt].mark){
tree[rl].mark += tree[rt].mark;
tree[rr].mark += tree[rt].mark;
tree[rt].sum += tree[rt].mark * (tree[rt].r - tree[rt].l + 1);
tree[rt].mark = 0;
}
if(r <= tree[rt].m)
return query(l, r, rl);
else if(l > tree[rt].m)
return query(l, r, rr);
else
return query(l, tree[rt].m, rl) + query(tree[rt].m + 1, r, rr);
}
int main(){
while(~scanf("%d %d", &n, &m)){
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
build(1, n, 1);
int x, y, z;
char c;
while(m--){
getchar();
c = getchar();
//printf("c:%c\n", c);
if(c == 'Q'){
scanf("%d %d", &x, &y);
printf("%lld\n", query(x, y, 1));
}
else{
scanf("%d %d %d", &x, &y, &z);
update(x, y, 1, z);
}
}
}
return 0;
}