树状数组(区间更新,区间查询)

Posted nonames

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组(区间更新,区间查询)相关的知识,希望对你有一定的参考价值。

Description

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

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

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

 

#include <iostream>
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include <stdio.h>
#include <string.h>
#define rep(i , n) for(int i = 0 ; i < (n) ; i++)
using namespace std;
const int N = 1000010 ;
long long ans = 0 , flag = 1;
long long a[200009] ,  sum1[200009] , sum2[200009];//sum1´æ²î·ÖD[i] £¬ sum2´æ(n-1)*D[i];

/*
= (D[1]) + (D[1]+D[2]) + ... + (D[1]+D[2]+...+D[n])
= n*D[1] + (n-1)*D[2] +... +D[n]
= n * (D[1]+D[2]+...+D[n]) - (0*D[1]+1*D[2]+...+(n-1)*D[n])

sum1[i] = D[i],sum2[i] = D[i]*(i-1)
*/
long long n , q ;
char c[5];
long long lowerbit(long long x)

    return x&(-x) ;


void update(long long x , long long value)

    long long m = x ;
    for(long long i = x ; i <= n ; i += lowerbit(i))
    
        sum1[i] += value ;
        sum2[i] += value * (m-1);
    


long long getsum(long long x)

    long long ans = 0 ;
    long long m = x ;
    for(int i = x ; i > 0 ; i -= lowerbit(i))
    
        ans += sum1[i] * m - sum2[i];
    
    return ans ;


int main()


    while(~scanf("%lld%lld" , &n , &q))
    
        memset(a , 0 , sizeof(a));
        for(int i = 1 ; i <= n ; i++)
        
            scanf("%lld" , &a[i]);
            update(i , a[i] - a[i-1]);
        
        for(int i = 0 ; i < q ; i++)
        
            scanf("%s" , c);
            if(c[0] == Q)
            
                long long l , r ;
                scanf("%lld%lld" , &l , &r);
                cout << getsum(r) - getsum(l-1) << endl ;
            
            else
            
                long long l , r , addval;
                scanf("%lld%lld%lld" , &l , &r , &addval);
                update(l , addval);
                update(r + 1 , -addval);
            
        
    



    return 0;

 

以上是关于树状数组(区间更新,区间查询)的主要内容,如果未能解决你的问题,请参考以下文章

一维树状数组区间更新区间查询

树状数组(区间更新,区间查询)

树状数组从入门到弃疗

树状数组 P3368区间更新 单点查询

树状数组区间更新区间查询

树状数组