0%

动态区间求和

给定一个长度为n的序列,有m个操作,需要实现区间加一个值和统计区间和。

输入描述:

第一行两个整数n和m,表示有一个长度为n个序列和m个操作。
第二行n个整数表示初始序列。
接下来m行,每行的内容属于以下一种:
Add x y a:把在区间[x,y]内的数都加上a(a∈[-10000,10000])。
Query x y:求出区间[x,y]中所有数的和。

输出描述:

对于每个询问输出相应的结果。

示例1
输入

5 5
1 2 3 4 5
Query 1 5
Add 1 3 5
Query 3 5
Add 3 5 10
Query 1 5

输出

15
17
60

说明

n,m<=10^5

lazy_seg_tree.cppview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <cstdio>
using namespace std;

const int N = 100010;

int n, m;
int A[N];
char s[100];

typedef long long LL;
struct node{
int L, R;
LL tag, sum;
int len(){ return (R-L+1);}

}tree[N<<2];

void up(int p){
tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;
}

void build(int L, int R, int p){
tree[p].L = L, tree[p].R =R;
if(L==R){
tree[p].sum = A[L];
return ;
}
int mid = L+R>>1;
build(L, mid, p<<1);
build(mid+1, R, p<<1|1);

up(p);
}

void down(int p){
LL &t = tree[p].tag;
if(t==0) return;
tree[p<<1].tag += t;
tree[p<<1].sum += t * tree[p<<1].len();

tree[p<<1|1].tag += t;
tree[p<<1|1].sum += t*tree[p<<1|1].len();

//清空懒标记
t = 0;
}

void update(int L, int R, int x, int p){
if(tree[p].L ==L && tree[p].R ==R){
tree[p].tag += x;
tree[p].sum += tree[p].len() * x; // forget;
//forget
return ;
}
down(p);
int mid = tree[p].L + tree[p].R >>1;
if(R<=mid) update(L, R, x, p<<1);
else if(L>mid) update(L, R, x, p<<1|1);
else {
update(L, mid, x, p<<1);
update(mid+1, R, x, p<<1|1);
}
up(p);
}

LL query(int L, int R, int p){
if(tree[p].L==L && tree[p].R==R){
return tree[p].sum;
}
// forget
down(p);
int mid = tree[p].L + tree[p].R >>1;
if(R<=mid) return query(L, R, p<<1);
else if(L>mid) return query(L, R, p<<1|1);
else {
return query(L, mid, p<<1) + query(mid+1, R, p<<1|1);
}
}


int main(){
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++) scanf("%d", &A[i]);
build(1, n, 1);
while(m--){
scanf("%s", s);
if(s[0]=='A'){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
update(a, b, c, 1);
}else{
int a, b;
scanf("%d%d", &a, &b);
printf("%lld\n", query(a, b, 1));
}

}
return 0;
}