AcWing 243. 一个简单的整数问题2(树状数组实现区间修改+区间查询)

简介: 笔记

AcWing243. 一个简单的整数问题2(树状数组实现区间修改+区间查询)


10.png


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


1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。


2、“Q l r”,表示询问 数列中第 l~r 个数的和。


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


输入格式

第一行两个整数N,M。


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


接下来M行表示M条指令,每条指令的格式如题目描述所示。


输出格式

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


每个答案占一行。


数据范围11.png


代码

#include <iostream>
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 res = 0;
    for(int i = x ; i ; i -= lowbit(i))   res += tr[i];
    return res;
}
LL prefix_sum(int x)
{
    return sum(tr1 , x) * (x + 1) - sum(tr2 , x);
}
int main()
{
    scanf("%d%d" , &n , &m);
    for(int i = 1; i <= n ; i++)    scanf("%d", &a[i]);
    for(int i = 1 ; i <= n ; i++)
    {
        int b = a[i] - a[i - 1];
        add(tr1 , i , b);
        add(tr2 , i , (LL)b * i);
    }
    while(m--)
    {
        int l , r , d;
        char op[2];
        scanf("%s%d%d" , op , &l , &r);
        if(*op == 'Q')
            cout << prefix_sum(r) - prefix_sum(l - 1) << endl;
        else
        {   
            scanf("%d" , &d);
            add(tr1 , l , d) , add(tr1 , r + 1 , -d);
            add(tr2 , l , l * d) , add(tr2 , r + 1 , (r + 1) * (- d));
        }
    }
        return 0;
}


目录
相关文章
|
8月前
|
C++
线段树的区间修改
线段树的区间修改
26 0
|
2月前
|
索引 NoSQL 容器
树状数组与线段树
树状数组与线段树
|
10月前
|
算法
数星星(树状数组模板题)
数星星(树状数组模板题)
30 0
|
人工智能 索引
树状数组总结
能够解决数据压缩里的累积频率的计算问题,现多用于高效计算数列的前缀和、区间和。
108 0
树状数组总结