树状数组

 一个简单的整数问题

给定一个长度为 N 的数列 A,以及 M 条指令,每条指令可能是以下两种之一:

  1. C l r d,表示把 A[l],A[l+1],,A[r] 都加上 d。
  2. Q l r,表示询问数列中第 lr 个数的和。

对于每个询问,输出一个整数表示答案。

输入格式

第一行两个整数 N,M

第二行 N 个整数 A[i]]。

接下来 M 行表示 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;
}

  



 
posted @ 2022-03-06 19:29  荣荣荣荣荣荣  阅读(29)  评论(0)    收藏  举报