树状数组 1 :单点修改,区间查询 Gym - 237040B

这是一道模板题。

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

 

  • "1 i x":给定 i,xi,x,将 a[i]a[i] 加上 xx;
  • "2 l r":给定 l,rl,r,求 ri=la[i]∑i=lra[i] 的值(换言之,求 a[l]+a[l+1]++a[r]a[l]+a[l+1]+⋯+a[r] 的值)。

 

Input

第一行包含 22 个正整数 n,qn,q,表示数列长度和询问个数。保证 1n,q1061≤n,q≤106。 第二行 nn 个整数 a[1],a[2],,a[n]a[1],a[2],…,a[n],表示初始数列。保证 |a[i]|106|a[i]|≤106。

接下来 qq 行,每行一个操作,为以下两种之一:

 

  • "1 i x":给定 i,xi,x,将 a[i]a[i] 加上 xx;
  • "2 l r":给定 l,rl,r,求 ri=la[i]∑i=lra[i] 的值。

 

保证 1lrn,1≤l≤r≤n, |x|106|x|≤106。

Output

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

Example

Input
3 2
1 2 3
1 2 0
2 1 3
Output
6

Note

对于所有数据,1n,q106,1≤n,q≤106, |a[i]|106|a[i]|≤106, 1lrn,1≤l≤r≤n, |x|106|x|≤106。

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
ll Case, n, m, i, j;
ll a[5000010]; 
inline void add(ll x, ll y) {
    for (ll i = x; i <= n; i += i & (-i)) {
        a[i] += y;
    }
}
inline ll getsum(ll x) {
    ll sum = 0;
    for (ll i = x; i; i -= i & (-i)) {
        sum += a[i];
    }
    return sum;
}
int main() {
    scanf("%lld%lld", &n, &m);
    for (i = 1; i <= n; i++) {
        ll x; scanf("%lld", &x);
        add(i, x);
    }
    for (i = 1; i <= m; i++) {
        ll type;
        scanf("%lld", &type);
        if (type == 1) {
            ll x, k;
            scanf("%lld%lld", &x, &k);
            add(x, k);
        }else{
            ll x, y;
            scanf("%lld%lld", &x, &y);
            printf("%lld\n", getsum(y) - getsum(x - 1));
        }
    }
}

 

posted @ 2021-01-04 20:19  XXXSANS  阅读(73)  评论(0编辑  收藏  举报