#include <iostream>
#include <iomanip>
#include <algorithm>
#include <array>
#include <cassert>
#include <utility>
#include <vector>

template <class InputIterator>
std::ostream& range_output(std::ostream& os_arg, InputIterator first_arg, InputIterator last_arg){ if(first_arg != last_arg){ do{ os_arg << *(first_arg++); if(first_arg == last_arg) break; os_arg << ' '; } while(true); }  return os_arg; }
template <class Tp> std::ostream& operator << (std::ostream& os_arg, const std::vector<Tp>& arr_arg){ return range_output(os_arg, arr_arg.cbegin(), arr_arg.cend()); }
template <class Tp, std::size_t Size> std::ostream& operator << (std::ostream& os_arg, const std::array<Tp, Size>& arr_arg){ return range_output(os_arg, arr_arg.cbegin(), arr_arg.cend()); }
template <class S, class T> std::ostream& operator << (std::ostream& os_arg, const std::pair<S, T>& pair_arg){ return os_arg << '(' << pair_arg.first << ", " << pair_arg.second << ')'; }

#ifndef ONLINE_JUDGE
    template <typename Head> void dump_out(Head head_arg){ std::cerr << head_arg << '\n'; }
    template <typename Head, typename... Tail>
    void dump_out(Head head_arg, Tail... tail_args){ std::cerr << head_arg << ", "; dump_out(tail_args...); }
    #define dump(...) do { std::cerr << "[in line " << __LINE__ << "] " << #__VA_ARGS__ << " : "; dump_out(__VA_ARGS__); } while(false)
#else
    #define dump(...) (void(0))
#endif


// @ Binary Indexed Tree (Fenwick Tree) のデータ構造  (オーバーフローに注意!)
//   * オンラインで累積和や二分探索が対数で計算可能 
//    (座標圧縮と組み合わせることで非有界なものにも適用可能)
//   * テンプレート引数 ; 型 (int や long long int)
template <class Integer_t = long long int, const Integer_t zero_Int = 0>
class BinaryIndexedTree {
private:
    int len;                       //  最大の大きさ (n)
    int log_len;                   //  2の冪乗が n を超えない最大の k (max k s.t. 2^k ≤ n)
    int power_log_len;             //  2の冪乗の長さ 2^k
    
    std::vector<Integer_t> data;   //  格納するデータ : data[i] := [iの立っている最下位bitを0にしたもの, i ) の和

    // サイズで0に初期化する補助関数
    void initialize_by_size(const int len){
        this -> len  = len; 
        for(log_len = 0, power_log_len = 1; 2 * power_log_len <= len; ++log_len, power_log_len *= 2);
        data.assign(len + 1, zero_Int);
    }
public:
    // コンストラクタ : 内容は全て 0 で初期化
    BinaryIndexedTree(const int len){ initialize_by_size(len); }
    template <class InputIterator>
    BinaryIndexedTree(InputIterator first, InputIterator last){
        initialize_by_size(last - first);
        for(int i = 1; i <= len; ++i, ++first){
            data[i] += *first;
            const int nxt_i = i + (i & -i); 
            if(nxt_i <= len) data[nxt_i] += data[i];
        }
    }

    // サイズの変更 : 内容は全て0で初期化 : 計算量 θ(N)
    void resize(const int len){ initialize_by_size(len); }

    // @ 点 index (0-indexed) に 値 value を加算する関数 : 計算量 O(log N)
    void add(int index, const Integer_t& value){
        for(++index; index <= len; index += index & -index) data[index] += value;
    }
    // @ 半開区間の累積和 [0, index) : (0-indexed) の総和を求める関数 : 計算量 O(log N)
    Integer_t sum(int index) const {
        Integer_t res = zero_Int;
        for(; index > 0; index -= index & -index) res += data[index];
        return res;
    }
    // @ 半開区間 [l, r) : (0-indexed) の総和を求める関数 : 計算量 O(log N)
    Integer_t sum(int l, int r) const {
        Integer_t res = zero_Int;
        for(; r > 0; r -= r & -r) res += data[r];
        for(; l > 0; l -= l & -l) res -= data[l];
        return res;
    }

    // @ 半開区間の累積和 S[0, idx) ≤ val となる最小の番号 idx (0-indexed) を返す関数 : 計算量 O(log N)
    // @ 注意 : (広義)単調増加する数列であることを仮定している.
    // @ 返り値は 0-indexed である. (ただし, 半開区間に注意！！！)
    int lower_bound(const Integer_t& val) const {
        int index = 0;
        Integer_t value = zero_Int;
        for(int power_len = power_log_len; power_len > 0; power_len /= 2){
            const int nxt_index = index + power_len;
            if(nxt_index < len){
                const Integer_t nxt_value = value + data[nxt_index];
                if(nxt_value < val){ value = nxt_value; index = nxt_index; }
            }
        }
        return index + 1;
    }
    // @ 半開区間の累積和 S[0, idx) < val となる最小の番号 idx (0-indexed) を返す関数 : 計算量 O(log N)
    // @ 注意 : (広義)単調増加する数列であることを仮定している.
    // @ 返り値は 0-indexed である (ただし, 半開区間に注意！！！)
    int upper_bound(const Integer_t& val) const {
        int index = 0;
        Integer_t value = zero_Int;
        for(int power_len = power_log_len; power_len > 0; power_len /= 2){
            const int nxt_index = index + power_len;
            if(nxt_index <= len){
                const Integer_t nxt_value = value + data[nxt_index];
                if(nxt_value <= val){ value = nxt_value; index = nxt_index; }
            }
        }
        return index + 1;
    }
};


int main(void){
    std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); 
    std::cout << std::fixed << std::setprecision(16);

    int n, q; std::cin >> n >> q;

    std::vector<int> A(n); for(auto& itr : A) std::cin >> itr;
    BinaryIndexedTree<long long int> BIT(A.cbegin(), A.cend());
    while(q--){
        char c; int a, b; std::cin >> c >> a >> b;
        if(c == '0') BIT.add(a, b);
        else std::cout << BIT.sum(a, b) << '\n';
    }
    return 0;
}

Measured memory_bytes: 10136