1. 程式人生 > 實用技巧 >樹狀陣列模板3

樹狀陣列模板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\n",getsum(r)-getsum(l-1)); } } }

題目連結