树状数组
一个简单的整数问题
给定一个长度为 N 的数列 A,以及 M 条指令,每条指令可能是以下两种之一:
C l r d,表示把 A[l],A[l+1],…,A[r] 都加上 d。Q l r,表示询问数列中第 l∼r 个数的和。
对于每个询问,输出一个整数表示答案。
输入格式
第一行两个整数 N,M。
第二行 N 个整数 A[i]]。
接下来 M 行表示 M 条指令,每条指令的格式如题目描述所示。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
数据范围
1 ≤ N , M ≤ 10^5
|d| ≤ 10000
|A[i]| ≤ 10^9
输入样例:
10 5
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
输出样例:
4
55
9
15
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010;
int n, m;
int a[N];
LL tr1[N], tr2[N];
int lowbit(int x)
{
return x & -x;
}
void add(LL tr[], int x, LL c){
for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
LL sum(LL tr[], int x){
LL cnt = 0;
for(int i = x; i; i -= lowbit(i)) cnt += tr[i];
return cnt;
}
LL prefix_sum(int x){
return sum(tr1, x) * (x + 1) - sum(tr2, x);
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++){
int x = a[i] - a[i - 1];
add(tr1, i, x);
add(tr2, i, (LL)x * i);
}
while(m --){
char c;
int l, r, d;
cin >> c;
if(c == 'C'){
cin >> l >> r >> d;
add(tr1, l, d), add(tr1, r + 1, -d);
add(tr2, l, l * d), add(tr2, r + 1, (r + 1) * -d);
}else{
cin >> l >> r;
//printf("l = %d r = %d\n",l,r);
printf("%lld\n",prefix_sum(r) - prefix_sum(l - 1));
}
}
return 0;
}

浙公网安备 33010602011771号