树状数组模板3

题目描述

这是一道模板题。

给定数列 a[1],a[2],...,a[n],你需要依次进行 q个操作,操作有两类:

  • 1 l r x:给定 l,r,x ,对于所有 i∈[l,r],将 a[i] 加上 x(换言之,将 a[l],a[l+1],...,a[r] 分别加上 x);
  • 2 l r:给定 l,r,求 ∑a[i] 的值(换言之,求 a[l]+a[l+1]+...+a[r] 的值)。

输入格式

第一行包含 2 个正整数 ,表示数列长度和询问个数。保证 1≤n,q≤1e6
第二行 n 个整数 a[1],a[2],...a[n],表示初始数列。保证 |a[i]|≤1e6
接下来 q 行,每行一个操作,为以下两种之一:

  • 1 l r x:对于所有 i∈[l,r],将 a[i] 加上 x
  • 2 l r:输出 ∑a[i] 的值。

保证 1≤l≤r≤n,|x|≤1e6 

输出格式

对于每个 2 l r 操作,输出一行,每行有一个整数,表示所求的结果。

样例

样例输入

5 10
2 6 6 1 1
2 1 4
1 2 5 10
2 1 3
2 2 3
1 2 2 8
1 2 3 7
1 4 4 10
2 1 2
1 4 5 6
2 3 4

样例输出

15
34
32
33
50
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+9;
const double ep=1e-7;
const int mod=1e9+7;
const double pi=acos(-1);
const int INF=INT_MAX;
#define mk make_pair
#define PII pair<int,int>
#define PIL pair<int,ll>
#define pb push_back
typedef long long ll;
ll n,q,tr[maxn],tre[maxn];
int lowbit(int x)
{
    return x&(-x);
}
void update(ll x,ll val)
{
    ll y=x;
    while(y<=n)
    {
        tr[y]+=val;
        tre[y]+=val*x;
        y+=lowbit(y);
    }
}
ll getsum(ll x)
{
    ll y=x,res=0;
    while(y)
    {
        res+=tr[y]*(x+1)-tre[y];
        y-=lowbit(y);
    }
    return res;
}
int main()
{
    scanf("%lld%lld",&n,&q);
    for(int i=1;i<=n;i++)
    {
        ll x;
        scanf("%lld",&x);
        update(i,x);
        update(i+1,-x);
    }
    while(q--)
    {
        int op,l,r;
        ll x;
        scanf("%d%d%d",&op,&l,&r);
        if(op==1)
        {
            scanf("%lld",&x);
            update(l,x);
            update(r+1,-x);
        }
        else
        {
            printf("%lld
",getsum(r)-getsum(l-1));
        }
    }
}

题目链接

欢迎加我qq1165750856一起玩呀~
原文地址:https://www.cnblogs.com/HHHEN/p/13418663.html