Problem:
Range Sum Query
Write a program which manipulates a sequence
A
= {
a
1
, a
2
, . . . , a
n
} with the following operations:
add(i, x)
: add
x
to
a
i
.
getSum(s, t)
: print the sum of
a
s
, a
s+1
,...,a
t
.
Note that the initial values of
a
i
(
i = 1, 2, . . . , n
) are 0.
Input
n
q
com
1
x
1
y
1
com
2
x
2
y
2
...
com
q
x
q
y
q
In the first line,
n
(the number of elements in
A
) and
q
(the number of queries) are given. Then,
q
queries are given where
com
represents the type of queries. '0' denotes
add(x
i
, y
i
)
and '1' denotes
getSum(x
i
, y
i
)
.
Output
For each
getSum
operation, print the sum in a line.
Constraints
1 ≤ n ≤ 100000
1 ≤ q ≤ 100000
If
com
i
is 0, then
1 ≤ x
i
≤ n
,
0 ≤ y
i
≤ 1000
.
If
com
i
is 1, then
1 ≤ x
i
≤ n
,
1 ≤ y
i
≤ n
.
Sample Input 1
3 5
0 1 1
0 2 2
0 3 3
1 1 2
1 2 2
Sample Output 1
3
2

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#include <bit>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using i128 = __int128_t;
using u128 = __uint128_t;
using pii = pair<int, int>;
using pic = pair<int, char>;
using pci = pair<char, int>;
using pll = pair<ll, ll>;
using pllc = pair<ll, char>;
#define rep(i, a, n) for (int i = a; i < (n); i++)

template <class T, class U>
struct PairHash {
  static inline size_t hash_combine(size_t seed, size_t v) noexcept {
    // boost::hash_combine と同等の混合
    return seed ^ (v + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2));
  }
  size_t operator()(const pair<T,U>& p) const noexcept {
    size_t h1 = std::hash<T>{}(p.first);
    size_t h2 = std::hash<U>{}(p.second);
    return hash_combine(h1, h2);
  }
};

pll operator+(const pll& a, const pll& b) {
  return {a.first + b.first, a.second + b.second};
}

pll operator-(const pll& a, const pll& b) {
  return {a.first - b.first, a.second - b.second};
}

pll operator-(const pll& a) {
  return {-a.first, -a.second};
}

// ===== プロトタイプ宣言 =====
int solve();

// ===== main関数 =====
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  return solve();
}


void prvec(vector<string> V) {
  for (const auto& v : V)
    cout << v << endl;
}

void prvec(vector<bool> V) {
  for (const auto& v : V)
    cout << boolalpha << setw(5) << setfill(' ') << v << " ";
  cout << endl;
}

template <typename T>
void prvec(vector<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(list<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(set<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(unordered_set<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T>
void prvec(multiset<T> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

template <typename T1>
void prvec(deque<T1> V) {
  for (const auto& v : V)
    cout << v << " ";
  cout << endl;
}

void prvec(set<pii> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(deque<pii> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(deque<pll> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pii> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pll> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

template <typename T1, typename T2>
void prvec(map<T1, T2> V) {
  for (const auto& [k, v] : V)
    cout << "{" << k << ": " << v << "}, ";
  cout << endl;
}

template <typename T1, typename T2, typename T3>
void prvec(map<T1, pair<T2, T3>> V) {
  for (const auto& [k, v] : V)
    cout << k << " : {" << v.first << " " << v.second << "}" << endl;
}

template <typename T1, typename T2, typename T3>
void prvec(map<T1, vector<pair<T2, T3>>> V) {
  for (const auto& [k, v] : V) {
    cout << k << " : " ;
    for (const auto& [a, b] : v)
      cout << "{" << a << ", " << b << "}, ";
    cout << endl;
  }
}

void prvec(map<int, bool> V) {
  for (const auto& [k, v] : V)
    cout << k << " : " << boolalpha << v << endl;
}

void prvec(map<string, pii> V) {
  for (const auto& [k, v] : V) 
    cout << k << " : " << v.first << " " << v.second << endl;
}

template <typename T>
void prvec(map<pii, T> V) {
  for (const auto& [k, v] : V) 
    cout << "{" << k.first << ", " << k.second << "}: " << v << endl;
}

void prvec(map<int, vector<int>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& v : vec) {
      cout << v << " ";
    }
    cout << endl;
  }
}

void prvec(map<char, vector<int>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& v : vec) {
      cout << v << " ";
    }
    cout << endl;
  }
}

void prvec(map<char, vector<pii>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& [a, b] : vec) {
      cout << "{" << a << ", " << b << "}, ";
    }
    cout << endl;
  }
}

void prvec(map<int, vector<pii>> V) {
  for (const auto& [k, vec] : V) {
    cout << k << " : ";
    for (const auto& [a, b] : vec) {
      cout << "{" << a << ", " << b << "}, ";
    }
    cout << endl;
  }
}

void prvec(map<int, stack<int>> V) {
  for (const auto& [k, stk] : V) {
    cout << k << " : ";
    stack<int> stk2 = stk;
    while (!stk2.empty()) {
      int v = stk2.top(); stk2.pop();
      cout << v << " ";
    }
    cout << endl;
  }
}

template <typename T1, typename T2>
void prvec(vector<pair<T1, T2>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<string, string>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<double, int>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<double, double>> V) {
  for (const auto& [a, b] : V)
    cout << fixed << setprecision(15)  << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<char, int>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<int, char>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

template <typename T1, typename T2>
void prvec(unordered_map<T1, T2> V) {
  for (const auto& [k, v] : V)
    cout << "{" << k << ": " << v << "}, ";
  cout << endl;
}

template <typename T1, typename T2>
void prvec(set<pair<T1, T2>> V) {
  for (const auto& [a, b] : V)
    cout << "{" << a << ", " << b << "}, ";
  cout << endl;
}

void prvec(vector<pair<int, vector<int>>> V) {
  for (const auto& [a, vec] : V) {
    cout << a << " : ";
    for (const auto& v : vec) cout << v << " ";
    cout << endl;
  }
}

void prvec(vector<pair<int, set<int>>> V) {
  for (const auto& [a, st] : V) {
    cout << a << " : ";
    for (const auto& v : st) cout << v << " ";
    cout << endl;
  }
}

template <typename T1, typename T2, typename T3>
void prvec(vector<tuple<T1, T2, T3>> V) {
  for (const auto& [a, b, c] : V)
    cout << "{" << a << ", " << b << ", " << c << "}, ";
  cout << endl;
}

template <typename T1, typename T2, typename T3>
void prvec(set<tuple<T1, T2, T3>> V) {
  for (const auto& [a, b, c] : V)
    cout << "{" << a << ", " << b << ", " << c << "}, ";
  cout << endl;
}

template <typename T1, typename T2, typename T3, typename T4>
void prvec(vector<tuple<T1, T2, T3, T4>> V) {
  for (const auto& [a, b, c, d] : V)
    cout << "{" << a << ", " << b << ", " << c << ", " << d << "}, ";
  cout << endl;
}

template<typename T, typename... Args>
void prvec(std::priority_queue<T, Args...> pq) {
    while (!pq.empty()) {
        auto [f, s] = pq.top();
        cout << "{" << f << ", " << s << "}, ";
        pq.pop();
    }
    cout << "\n";
}

class UnionFind {
  private :
    vector<int> parent;
    vector<int> sz;
    vector<int> edge_count;
  
  public :
    UnionFind(int n) : parent(n), sz(n, 1), edge_count(n, 0) {
      for (int i = 0; i < n; i++) parent[i] = i;
    }
    
    int find(int x) {
      if (parent[x] == x) return x;
      return parent[x] = find(parent[x]);
    }
    
    bool unite(int x, int y) {
      int rootX = find(x);
      int rootY = find(y);
      if (rootX == rootY) {
      	edge_count[rootX]++;
      	return false; // cycle検出
      }
      
      if (sz[rootX] < sz[rootY]) swap(rootX, rootY);
      parent[rootY] = rootX;
      sz[rootX] += sz[rootY];
      edge_count[rootX] += edge_count[rootY] + 1;
      return true;
    }
    
    int getSize(int x) {
      return sz[find(x)];
    }
    
    int getEdges(int x) {
    	return edge_count[find(x)];
    }
    
    bool same(int x, int y) {
      return find(x) == find(y);
    }
    
    // 頂点数を new_n まで増やす (new_n <= 現在のサイズなら何もしない)
    void ensureSize(int new_n) {
        int old_n = parent.size();
        if (new_n <= old_n) return;
        parent.resize(new_n);
        sz.resize(new_n, 1);
        edge_count.resize(new_n, 0);
        // 新しく追加された i (old_n <= i < new_n) をルート＋サイズ1に初期化
        for (int i = old_n; i < new_n; i++) {
            parent[i] = i;
            // sz[i] は resize の第二引数で 1 になっている
        }
    }
    
    // 頂点を1つ追加して、そのインデックスを返す
    int addVertex() {
        int idx = parent.size();
        parent.push_back(idx);
        sz.push_back(1);
        edge_count.push_back(0);
        return idx;
    }    
};

template <class Abel>
// 重み付きUnionFindの定義
struct WeightedUnionFind {
  vector<int> parent, size;
  vector<Abel> diff_weight;

  WeightedUnionFind(int n)
    : parent(n), size(n, 1), diff_weight(n, Abel{}) {
    iota(parent.begin(), parent.end(), 0);
  }

  int find(int x) {
    if (parent[x] == x) return x;
    int r = find(parent[x]);
    diff_weight[x] = diff_weight[x] + diff_weight[parent[x]];
    return parent[x] = r;
  }

  Abel weight(int x) {
    find(x);
    return diff_weight[x];
  }

  bool unite(int u, int v, Abel w) {
    Abel wu = weight(u), wv = weight(v);
    int ru = find(u), rv = find(v);
    if (ru == rv) {
      return (wv - wu == w); // すでに矛盾ないかチェック
    }

    Abel dw = w + wu - wv;

    // union by size（大きいほうに小さいほうをつける）
    if (size[ru] < size[rv]) {
      swap(ru, rv);
      swap(u, v);
      dw = -dw;
    }

    parent[rv] = ru;
    diff_weight[rv] = dw;
    size[ru] += size[rv];
    return true;
  }

  bool same(int x, int y) {
    return find(x) == find(y);
  }

  Abel diff(int x, int y) {
    return weight(y) - weight(x);
  }
};

struct DSURollback {
  int n;
  vector<int> parent, sz;

  // 変更履歴: (結合された子root, 併合前の親rootのサイズ)
  // 子root = -1 は「何も結合しなかった(uniteで同根)」の印
  vector<pair<int,int>> hist;

  DSURollback(int n=0): n(n), parent(n), sz(n,1) {
    iota(parent.begin(), parent.end(), 0);
  }

  int find(int x) const {
    // パス圧縮しない
    while (parent[x] != x) x = parent[x];
    return x;
  }

  bool unite(int x, int y) {
    x = find(x); y = find(y);
    if (x == y) { 
      hist.emplace_back(-1, 0); // ダミー (巻き戻し整合用)
      return false; 
    }
    if (sz[x] < sz[y]) swap(x, y); // x に y をくっつける（サイズ併合）

    // 履歴に「y が x にぶら下がる前の x のサイズ」を記録
    hist.emplace_back(y, sz[x]);

    parent[y] = x;
    sz[x] += sz[y];
    return true;
  }

  // 直前の unite を 1 回取り消す
  void rollback() {
    auto [y, old_szx] = hist.back(); hist.pop_back();
    if (y == -1) return; // 何もしていない unite の取消
    int x = parent[y];
    // 親子関係とサイズを元に戻す
    parent[y] = y;
    sz[x] = old_szx;
  }

  // スナップショット（この位置まで戻せる）
  int snapshot() const { return (int)hist.size(); }

  // 指定スナップショットへ戻す（複数回分まとめて取り消し）
  void rollback_to(int snap) {
    while ((int)hist.size() > snap) rollback();
  }

  bool same(int a, int b) { return find(a) == find(b); }
  int size(int x) { return sz[find(x)]; }
};

template<class S, class Op, class E>
struct SegTree {
  int n0 = 0;   // 元の配列の長さ
  int n  = 1;   // セグ木内部のサイズ(2べき)
  std::vector<S> d;

  Op op{};  // 区間結合
  E  e{};   // 単位元

  SegTree() = default;
  explicit SegTree(int n_)      { init(n_); }
  explicit SegTree(const std::vector<S>& a) { init(a); }

  // 要素数 n_ で初期化（全部 e()）
  void init(int n_) {
    n0 = n_;
    n = 1;
    while (n < n_) n <<= 1;
    d.assign(2 * n, e());
  }

  // 初期配列 a から構築
  void init(const std::vector<S>& a) {
    init((int)a.size());
    for (int i = 0; i < n0; i++) d[n + i] = a[i];
    for (int i = n - 1; i >= 1; i--) {
      d[i] = op(d[i << 1], d[i << 1 | 1]);
    }
  }

  // 点代入: A[pos] = val
  void point_set(int pos, const S& val) {
    int k = pos + n;
    d[k] = val;
    for (k >>= 1; k; k >>= 1) {
      d[k] = op(d[k << 1], d[k << 1 | 1]);
    }
  }

  // 点取得
  S get(int pos) const {
    return d[pos + n];
  }

  // 区間 [l, r) を畳み込み（LazySegTree に合わせて prod という名前に）
  S prod(int l, int r) const {
    S L = e(), R = e();
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) L = op(L, d[l++]);
      if (r & 1) R = op(d[--r], R);
    }
    return op(L, R);
  }

  // 全体
  S all_prod() const {
    return d[1];
  }
};

// 区間和
struct OpSum {
  ll operator()(ll a, ll b) const { return a + b; }
};

// 単位元（0）
struct ESum {
  ll operator()() const { return 0LL; }
};

// usage: RSQ(SegTreeSum)
  // int n = 10;
  // SegTree<ll, OpSum, ESum> seg(n);
  
  // // A[i] = i をセット
  // for (int i = 0; i < n; i++) seg.point_set(i, i);

  // // [l, r) の和
  // ll s = seg.prod(2, 7);

// 区間最大
struct OpMax {
  ll operator()(ll a, ll b) const { return std::max(a, b); }
};

struct EMax {
  static constexpr ll NEG_INF = (ll)-4e18;
  ll operator()() const { return NEG_INF; }
};
// usage: RMaxQ(SegTree)
// SegTree<ll, OpMax, EMax> seg_max(n);

// 区間最小
struct OpMin {
  ll operator()(ll a, ll b) const { return std::min(a, b); }
};

struct EMin {
  static constexpr ll INF = (ll)4e18;
  ll operator()() const { return INF; }
};
// usage: RMinQ(SeegTree)
// SegTree<ll, OpMin, EMin> seg_min(n);

// SegTreeMinArg
struct MinArgNode {
  long long val;
  int idx;
};

// 区間最小 & argmin
struct OpMinArg {
  MinArgNode operator()(const MinArgNode& a, const MinArgNode& b) const {
    if (a.val != b.val) return (a.val < b.val ? a : b);
    if (a.idx == -1)    return b;
    if (b.idx == -1)    return a;
    return (a.idx < b.idx ? a : b); // tie: 小さい idx
  }
};

struct EMinArg {
  static constexpr long long INF = (long long)4e18;
  MinArgNode operator()() const { return MinArgNode{INF, -1}; }
};
// usage: SegTreeMinArg
// int n = 10;
// SegTree<MinArgNode, OpMinArg, EMinArg> seg_minarg(n);

// // 値だけ代入する糖衣
// auto point_set_val = [&](int pos, long long v) {
//   seg_minarg.point_set(pos, MinArgNode{v, pos});
// };

// point_set_val(3, 5);
// point_set_val(7, 2);

// MinArgNode res = seg_minarg.prod(0, n); // 全区間の最小 & その位置

// ==============================
// Generic Lazy Segment Tree
// S: ノード型（例: {val, len}）
// F: 遅延（写像）型（例: 加算値）
// 必要な関数: 
//   op(S,S)->S                : 区間結合（モノイド演算）
//   e()->S                    : Sの単位元
//   mapping(F,S)->S           : SにFを適用
//   composition(Fnew, Fold)->F: 遅延の合成（先にFold→後でFnewがかかる形になるよう定義）
//   id()->F                   : Fの単位元
// ==============================
template<
  class S, class F,
  class Op, class E,
  class Mapping, class Composition, class Id
>
struct LazySegTree {
  int n = 0, size = 1, logn = 0;

  // ここで中の演算子たちをデフォルト初期化
  Op         op{};
  E          e{};
  Mapping    mapping{};
  Composition composition{};
  Id          id{};

  std::vector<S> d;
  std::vector<F> lz;

  LazySegTree() = default;
  explicit LazySegTree(int n_) { init(n_); }
  explicit LazySegTree(const std::vector<S>& a) { init(a); }

  void init(int n_) {
    n = n_;
    logn = 0;
    size = 1;
    while (size < n) size <<= 1, ++logn;
    d.assign(2 * size, e());   // E::operator() で単位元
    lz.assign(size, id());     // Id::operator() で遅延の単位元
  }

  void init(const std::vector<S>& a) {
    init((int)a.size());
    for (int i = 0; i < n; i++) d[size + i] = a[i];
    for (int i = size - 1; i >= 1; i--) pull(i);
  }

  void set_point(int p, const S& x) {
    p += size;
    for (int i = logn; i >= 1; i--) push(p >> i);
    d[p] = x;
    for (int i = 1; i <= logn; i++) pull(p >> i);
  }

  S get_point(int p) {
    p += size;
    for (int i = logn; i >= 1; i--) push(p >> i);
    return d[p];
  }

  // 区間 [l, r) に f を適用
  void apply(int l, int r, const F& f) {
    if (l >= r) return;
    l += size; r += size;
    int l0 = l, r0 = r;
    for (int i = logn; i >= 1; i--) {
      if (((l0 >> i) << i) != l0) push(l0 >> i);
      if (((r0 >> i) << i) != r0) push((r0 - 1) >> i);
    }
    while (l < r) {
      if (l & 1) all_apply(l++, f);
      if (r & 1) all_apply(--r, f);
      l >>= 1; r >>= 1;
    }
    for (int i = 1; i <= logn; i++) {
      if (((l0 >> i) << i) != l0) pull(l0 >> i);
      if (((r0 >> i) << i) != r0) pull((r0 - 1) >> i);
    }
  }

  // 区間 [l, r) を畳み込み
  S prod(int l, int r) {
    if (l >= r) return e();
    l += size; r += size;
    for (int i = logn; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }
    S sml = e(), smr = e();
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1; r >>= 1;
    }
    return op(sml, smr);
  }

  // 全体
  S all_prod() const { return d[1]; }

private:
  void pull(int k) { d[k] = op(d[2*k], d[2*k+1]); }

  void all_apply(int k, const F& f) {
    d[k] = mapping(f, d[k]);
    if (k < size) lz[k] = composition(f, lz[k]);
  }

  void push(int k) {
    if (lz[k] != id()) { // F 型同士の比較（例: long long）
      all_apply(2*k,   lz[k]);
      all_apply(2*k+1, lz[k]);
      lz[k] = id();
    }
  }
};

// ==============================
// ここから具体インスタンス例
// 共通ノード型（lenを持たせることで sum/max の両方に対応）
// ==============================
struct Node {
  long long val; // 区間の値（和 or 最大）
  int len;       // その区間の長さ（sumでのみ使用）
};

// -------- Range Add + Range Sum 用の関数群 --------
struct OpSumlazy {
  Node operator()(const Node& a, const Node& b) const {
    return Node{a.val + b.val, a.len + b.len};
  }
};
struct ESumlazy {
  Node operator()() const { return Node{0LL, 0}; } // 単位元
};
struct MappingAddToSum {
  Node operator()(long long add, const Node& s) const {
    return Node{s.val + add * 1LL * s.len, s.len};
  }
};
struct ComposeAdd {
  long long operator()(long long fnew, long long fold) const {
    return fnew + fold;
  }
};
struct IdAdd {
  long long operator()() const { return 0LL; }
};

// Range Add + Range Max
static constexpr long long NEG_INF = -(1LL<<60);
struct OpMaxlazy {
  Node operator()(const Node& a, const Node& b) const {
    return Node{std::max(a.val, b.val), a.len + b.len};
  }
};
struct EMaxlazy {
  Node operator()() const { return Node{NEG_INF, 0}; }
};
struct MappingAddToMax {
  Node operator()(long long add, const Node& s) const {
    return Node{s.val + add, s.len};
  }
};

// ==============================
// 使用例1: Range Add + Range Sum
// ==============================
void example_sum() {
  int n = 8;
  std::vector<Node> init(n, Node{0, 1});

  LazySegTree<Node, long long,
              OpSumlazy, ESumlazy,
              MappingAddToSum, ComposeAdd, IdAdd>
    seg(init);   // ← もう functor を渡さなくてよい

  seg.apply(2, 6, 5);           // [2, 6) に +5
  std::cout << seg.all_prod().val << "\n";    // 20
  std::cout << seg.prod(3, 5).val << "\n";    // 10
}

// ==============================
// 使用例2: Range Add + Range Max
// ==============================
void example_max() {
  int n = 10;
  std::vector<Node> init(n, Node{0, 1});

  LazySegTree<Node, long long,
              OpMaxlazy, EMaxlazy,
              MappingAddToMax, ComposeAdd, IdAdd>
    seg(init);   // ここも functor いらない

  seg.apply(2, 5, 1);
  seg.apply(4, 9, 3);
  std::cout << seg.all_prod().val << "\n";
}

// 1-indexed Fenwick Tree (Binary Indexed Tree)
template <class T>
struct Fenwick {
  int n;
  vector<T> bit;

  Fenwick() : n(0) {}
  explicit Fenwick(int n) : n(n), bit(n + 1, T{}) {}

  // a[idx] += delta
  void add(int idx, T delta) {
    for (; idx <= n; idx += idx & -idx) bit[idx] += delta;
  }

  // prefix sum: a[1] + ... + a[idx]
  T sum(int idx) const {
    T s{};
    for (; idx > 0; idx -= idx & -idx) s += bit[idx];
    return s;
  }

  // range sum: a[l] + ... + a[r]
  T range_sum(int l, int r) const {
    if (l > r) return T{};
    return sum(r) - sum(l - 1);
  }

  // ---- ここから先は「順序統計」をやりたい人向けのオプション ----
  // すべての要素が「非負の整数」である前提で、
  // 最小の idx を返す: sum(idx) >= t  (tは1..sum(n))
  // T が整数型のときのみ有効化
  template <class U = T, std::enable_if_t<std::is_integral_v<U>, int> = 0>
  int kth(U t) const {
    // 前提: すべての add が非負、bitの総和 >= t
    int idx = 0;
    U acc = 0;
    int step = 1;
    while ((step << 1) <= n) step <<= 1; // n以下の最大2冪
    for (int p = step; p; p >>= 1) {
      int nx = idx + p;
      if (nx <= n && acc + (U)bit[nx] < t) {
        acc += (U)bit[nx];
        idx = nx;
      }
    }
    return idx + 1; // 1-indexed
  }
};
 
// ===== 素数判定を行う =====
struct MillerRabin64 {
  static inline ull mul_mod(ull a, ull b, ull mod) {
    return (ull)((u128)a * b % mod);
  }
  static inline ull pow_mod(ull a, ull e, ull mod) {
    ull r = 1 % mod;
    a %= mod;
    while (e) {
      if (e & 1) r = mul_mod(r, a, mod);
      a = mul_mod(a, a, mod);
      e >>= 1;
    }
    return r;
  }
  static bool isPrime(ull n) {
    if (n < 2) return false;
    // 小さい素数で先に弾く
    static const ull smalls[] = {2,3,5,7,11,13,17,19,23,29,31,37};
    for (ull p : smalls) {
      if (n == p) return true;
      if (n % p == 0) return n == p;
    }
    // n-1 = d * 2^s2
    ull d = n - 1, s2 = 0;
    while (!(d & 1)) d >>= 1, ++s2;

    auto witness = [&](ull a) -> bool {
      if (!(a % n)) return false;
      ull x = pow_mod(a, d, n);
      if (x == 1 || x == n - 1) return false;
      for (ull i = 1; i < s2; i++) {
        x = mul_mod(x, x, n);
        if (x == n - 1) return false;
      }
      return true; // 合成数の証人
    };

    // 64bit 決定的基底
    static const ull bases[] = {
      2ULL, 325ULL, 9375ULL, 28178ULL,
      450775ULL, 9780504ULL, 1795265022ULL
    };
    for (ull a : bases) {
      if (!(a % n)) continue;
      if (witness(a)) return false;
    }
    return true;
  }
};
using MR64 = MillerRabin64;

// modint: mod計算をintを扱うように扱える構造体
// https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a#8-modint
template<int MOD> struct Fp {
  ll val;
  constexpr Fp(ll v = 0) noexcept : val(v % MOD) {
    if (val < 0) val += MOD;
  }
  constexpr int getmod() { return MOD; }
  constexpr Fp operator - () const noexcept {
    return val ? MOD - val : 0;
  }
  constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r;}
  constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r;}
  constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r;}
  constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r;}
  constexpr Fp& operator += (const Fp& r) noexcept {
    val += r.val;
    if (val >= MOD) val -= MOD;
    return *this;
  }
  constexpr Fp& operator -= (const Fp& r) noexcept {
    val -= r.val;
    if (val < 0) val += MOD;
    return *this;
  }
  constexpr Fp& operator *= (const Fp& r) noexcept {
    val = val * r.val % MOD;
    return *this;
  }
  constexpr Fp& operator /= (const Fp& r) noexcept {
    return *this *= modpow(r, MOD - 2);
  }
  // 前置 ++x
  constexpr Fp& operator++() noexcept {
    val++;
    if (val >= MOD) val -= MOD;
    return *this;
  }

  // 後置 x++
  constexpr Fp operator++(int) noexcept {
    Fp tmp = *this;
    ++(*this);
    return tmp;
  }

  // 前置 --x
  constexpr Fp& operator--() noexcept {
    val--;
    if (val < 0) val += MOD;
    return *this;
  }

  // 後置 x--
  constexpr Fp operator--(int) noexcept {
    Fp tmp = *this;
    --(*this);
    return tmp;
  }
  constexpr bool operator == (const Fp& r) const noexcept {
    return this->val == r.val;
  }
  constexpr bool operator != (const Fp& r) const noexcept {
    return this->val != r.val;
  }
  constexpr bool operator < (const Fp& r) const noexcept { return this->val < r.val;}
  constexpr bool operator <= (const Fp& r) const noexcept { return this->val <= r.val;}
  constexpr bool operator > (const Fp& r) const noexcept { return this->val > r.val;}
  constexpr bool operator >= (const Fp& r) const noexcept { return this->val >= r.val;}
  friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) {
    return os << x.val;
  }
  friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) {
    ll v;
    is >> v;
    x = Fp<MOD>(v);
    return is;
  }
  friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, ll n) noexcept {
    if (n == 0) return 1;
    auto t = modpow(a, n / 2);
    t = t * t;
    if (n & 1) t = t * a;
    return t;
  }
};
using mint = Fp<998244353>;

int solve() {
  int n, q;
  cin >> n >> q;
  
  int size = 1;
  while (size < n) size <<= 1;
  const int SEG_LEN = size;
  vector<ll> seg_tree(SEG_LEN * 2, 0);
  
  auto add = [&](int idx, ll x) -> void {
      idx += SEG_LEN - 1;
      seg_tree[idx] += x;
      for (idx >>= 1; idx >= 1; idx >>= 1) {
          seg_tree[idx] = seg_tree[idx * 2] + seg_tree[idx * 2 + 1];
      }
  };
  
  auto sum_main = [&](auto&& self, int ql, int qr, int sl, int sr, int pos) -> ll {
    // 範囲外
    if (sr <= ql || sl >= qr) return 0;
    // 完全に含まれる
    if (ql <= sl && sr <= qr) return seg_tree[pos];
    // 部分的に含まれる-> 子を検索
    int m = (sl + sr) >> 1;
    ll left = self(self, ql, qr, sl, m, pos * 2);
    ll right = self(self, ql, qr, m, sr, pos * 2 + 1);
    return left + right;
  };
  
  auto getSum = [&](int l, int r) -> ll {
    return sum_main(sum_main, l, r, 1, SEG_LEN + 1, 1)  ;
  };
  
  while (q--) {
      int com; ll x, y; cin >> com >> x >> y;
      
      if (com == 0) add(x, y);
      else cout << getSum(x, y + 1) << "\n";
  }
  
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 5476
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct SegmentTree {
    int SEG_LEN;
    vector<ll> tree;

    SegmentTree(int size) {
        SEG_LEN = 1;
        while (SEG_LEN < size) SEG_LEN <<= 1;
        tree.assign(2*SEG_LEN, 0);
    }

    void update(int index, ll x) {
        index += SEG_LEN;
        tree[index] += x;
        while (index > 1) {
            index >>= 1;
            tree[index] = tree[index*2] + tree[index*2+1];
        }
    }

    //[l, r]の最小値を取得
    ll query(int l, int r) {
        l += SEG_LEN;
        r += SEG_LEN + 1; //閉区間 [l,r]に対応

        ll result = 0;
        while (l < r) {
            if (l & 1) result += tree[l++];
            if (r & 1) result += tree[--r];
            l >>= 1;
            r >>= 1;
        }
        return result;
    }
};

int main() {
    int N, Q;
    cin >> N >> Q;

    SegmentTree seg(N);
    for (int qi = 0; qi < Q; qi++) {
        int type; cin >> type;
        if (type == 0) {
            int index; ll x;
            cin >> index >> x;
            seg.update(index, x);
        } else if (type == 1) {
            int s, t;
            cin >> s >> t;
            ll result = seg.query(s, t);
            cout << result << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 5040
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vvvll = vector<vector<vector<ll>>>;
using vd = vector<double>;
using vvd = vector<vector<double>>;
using vstr = vector<string>;
using vchar = vector<char>;
using vvchar = vector<vector<char>>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using vvvb = vector<vector<vector<bool>>>;
using pii = pair<int,int>;
using pll = pair<long long, long long>;
using Graph = vector<vector<int>>;
using WeightedGraph = vector<vector<pair<int,ll>>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(ll i = (ll)a; i < (ll)b; i++)
#define REP(i, a, b) for (ll i = (ll)a; i <= (ll)b; i++)
#define rrep(i, a, b) for(ll i = (ll)b-1; i >= (ll)a; i--)
#define RREP(i, a, b) for(ll i = (ll)b; i >= (ll)a; i--)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define spa " "
#define mint modint<MOD>

const int inf = 1070000000;
const long long INF = 4500000000000000000;
//const long long MOD = 998244353;
const long long MOD = 1000000007;
const double pi = 3.141592653589793238;
const double eps = (1e-10);
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";

template<typename T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<typename T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template<typename S, typename T> pair<S, T> operator+(pair<S, T> a, pair<S, T> b) {
    pair<S, T> ans;
    ans.first = a.first + b.first;
    ans.second = a.second + b.second;
    return ans;
} 
template<typename T> vector<T> operator+(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size());
    vector<T> c(N);
    for(int i = 0; i < N; i++) {
        if(i >= a.size()) c[i] = b[i];
        else if(i >= b.size()) c[i] = a[i];
        else c[i] = a[i] + b[i];
    }
    return c;
}
template<typename T> vector<T> operator*(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size()), n = min(a.size(), b.size());
    vector<T> c(N, 0);
    for(int i = 0; i < n; i++) {
        c[i] = a[i] * b[i];
    }
    return c;
}

//拡張ユークリッド
ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if(b == 0) {
        x = 1, y = 0;
        return a;
    }

    ll q = a/b;
    ll g = ext_gcd(b, a-q*b, x, y);
    ll z = x-q*y;
    x = y, y = z;
    return g;
}
//mod mにおけるaの逆元. aとmは互いに素.
ll inverse(ll a, ll m) {
    ll x, y;
    ext_gcd(a, m, x, y);
    x = (x+m) % m;
    return x;
}
//modint
template<std::uint_fast64_t mod> struct modint {
    using u64 = std::uint_fast64_t;
    u64 val;

    modint(u64 v = 0) : val(v % mod) {}

    bool operator==(modint other) {
        return val == other.val;
    }
    bool operator<(const modint& other) const {
        return val < other.val;
    }
    // operator> (大なり)
    bool operator>(const modint& other) const {
        return val > other.val;
    }
    modint operator+(modint other) {
        modint<mod> ans;
        ans.val = val + other.val;
        if(ans.val >= mod) ans.val -= mod;
        return ans;
    }
    modint operator-(modint other) {
        modint<mod> ans;
        if(val < other.val) val += mod;
        ans.val = val - other.val;
        return ans;
    }
    modint operator*(modint other) {
        modint<mod> ans;
        ans.val = (val * other.val) % mod;
        return ans;
    }
    modint operator/(modint other) {
        modint<mod> ans;
        ans.val = (val * inverse(other.val, mod)) % mod;
        return ans;
    }
    modint &operator+=(modint other) {
        *this = *this + other;
        return *this;
    }
    modint &operator-=(modint other) {
        *this = *this - other;
        return *this;
    }
    modint &operator*=(modint other) {
        *this = *this * other;
        return *this;
    }
    modint &operator/=(modint other) {
        *this = *this / other;
        return *this;
    }
    modint &operator++() {
        *this += 1;
        return *this;
    }
    modint &operator++(int) {
        ++(*this);
        return *this;
    }
    modint &operator--() {
        *this -= 1;
        return *this;
    }
    modint &operator--(int) {
        --(*this);
        return *this;
    }
};
//modintの入出力
template<std::uint_fast64_t mod> std::ostream& operator<<(std::ostream &os, const modint<mod> &x) {
    // modint の 'val' メンバを出力ストリーム(os)に渡す
    os << x.val;
    return os; // ストリームを返す (チェーンのため)
}
template<std::uint_fast64_t mod> std::istream& operator>>(std::istream& is, modint<mod> &x) {
    // modintが内部で使っているu64型を取得
    using u64 = typename modint<mod>::u64; 
    
    u64 input_value;
    is >> input_value; // (1) istream(cin) から一時変数に値を読み込む
    
    // (2) 読み込んだ値を使って modint を再構築する
    //     modintのコンストラクタが (input_value % mod) を処理してくれる
    x = modint<mod>(input_value); 
    
    return is; // (3) ストリームを返す (チェーンのため)
}
//累乗, x^n
template<typename T> T pow(T x, int n) {
    T ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
//階乗, n!
template<typename T> T fact(T n) {
    if(n == 0) return 1;
    return n * fact(n-1);
}
//nPk
template<typename T> T perm(T n, T k) {
    if(k == 0) return 1;
    return n * perm(n-1, k-1);
}
//nCk
template<typename T> T comb(T n, T k) {
    if(k > n) return 0;
    return perm(n, min(k, n-k))/fact(min(k, n-k));
}
//ord(n)
ll ord(ll n, ll p) {
    int ans = 0;
    while(n % p == 0) {
        n /= p;
        ans++;
    }
    return ans;
}
//ルジャンドルの公式ord(n!)
ll factord(ll n, ll p) {
    ll ans = 0;
    ll q = p, tmp = n;
    while(tmp > 0) {
        tmp = n/q;
        ans += tmp;
        q *= p;
    }
    return ans;
}
//素因数分解, O(√N)
vector<pair<ll,ll>> factorize(ll N) {
    vector<pair<ll,ll>> ans;
    for(ll p = 2; p*p <= N; p++) {
        int ex = 0;
        while(N % p == 0) {
            N /= p;
            ex++;
        }
        if(ex != 0) ans.push_back({p,ex});
    }
    if(N != 1) ans.push_back({N,1});
    return ans;
}
//素数判定
bool isprime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}
//エラトステネスの篩
struct Eratosthenes {
    vector<bool> prime;
    vector<int> minfactor;
    vector<int> mobius;
    vector<ll> euler;

    //コンストラクタ O(NloglogN)
    Eratosthenes(int N) : prime(N+1, true),
                          minfactor(N+1, -1),
                          mobius(N+1, 1),
                          euler(N+1, 1) {
        prime[0] = false;
        prime[1] = false;
        minfactor[1] = 1;
        REP(i,1,N) euler[i] = i;

        for(int p = 2; p <= N; p++) {
            if(!prime[p]) continue;

            minfactor[p] = p;
            mobius[p] = -1;
            euler[p] = p-1;

            for(int q = 2; p*q <= N; q++) {
                prime[p*q] = false;
                if(minfactor[p*q] == -1) minfactor[p*q] = p;
                if(q % p == 0) mobius[p*q] = 0;
                else mobius[p*q] *= -1;
                euler[p*q] = euler[p*q]*(p-1)/p;
            }
        }
    }

    //素因数分解 O(logn)
    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> ans;
        while(n > 1) {
            int p = minfactor[n], exp = 0;
            while(n % p == 0) {
                n /= p;
                exp++;
            }
            ans.push_back({p, exp});
        }
        return ans;
    }
    //約数列挙 O(σ(n))
    vector<int> divisors(int n) {
        vector<int> ans = {1};
        while(n > 1) {
            int p = minfactor[n], d = 1, s = ans.size();
            while(n % p == 0) {
                d *= p;
                for(int i = 0; i < s; i++) {
                    ans.push_back(ans[i]*d);
                }
                n /= p;
            }
        }
        return ans;
    }
    //素数関数 O(n)
    int count(int n) {
        int ans = 0;
        REP(i,2,n) if(prime[i]) ans++;
        return ans;
    }
};
//高速ゼータ変換
template<typename T> void fast_zeta(vector<T> &f) {
    int N = f.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;
        
        for(int k = N/p; k >= 1; k--) {
            f[k] += f[k*p];
        }
    }
}
//高速メビウス変換
template<typename T> void fast_mobius(vector<T> &F) {
    int N = F.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;

        for(int k = 1; k*p <= N; k++) {
            F[k] -= F[k*p];
        }
    }
}
//添字GCD畳み込み
template<typename T> vector<T> gcd_conv(vector<T> &f, vector<T> &g) {
    int N = max(f.size(), g.size());
    vector<T> F(N, 0), G(N, 0), H(N);
    for(int i = 0; i < f.size(); i++) F[i] = f[i];
    for(int i = 0; i < g.size(); i++) G[i] = g[i];
    fast_zeta(F);
    fast_zeta(G);
    
    for(int i = 0; i < N; i++) H[i] = F[i]*G[i];
    fast_mobius(H);
    
    return H;
}

//行列積
template<typename T> vector<vector<T>> matrix_product(vector<vector<T>> A, vector<vector<T>> B) {
    int H = A.size(), W = A[0].size(), P = B.size(), Q = B[0].size();
    if(W != P) {
        cout << "matrix_size_error" << "\n";
        return vector<vector<T>>(0);
    }

    vector<vector<T>> C(H, vector<T>(Q, 0));
    rep(i,0,H) rep(j,0,Q) {
        rep(k,0,W) {
            C[i][j] += A[i][k]*B[k][j];
        }
    }
    return C;
}
//行列累乗
template<typename T> vector<vector<T>> matrix_pow(vector<vector<T>> A, ll n) {
    int N = A.size();
    vector<vector<T>> ans(N, vector<T>(N, 0));
    rep(i,0,N) ans[i][i] = 1;
    
    while(n > 0) {
        if(n & 1) ans = matrix_product(ans, A);
        A = matrix_product(A, A);
        n >>= 1; 
    }
    return ans;
}

//1+2+...+n = n(n+1)/2
ll tri(ll n) {
    ll x = n*(n+1);
    return x/2;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転, 左回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
long double dist(pair<long double, long double> a, pair<long double, long double> b) {
    return sqrt((a.first-b.first)*(a.first-b.first) + (a.second-b.second)*(a.second-b.second));
}
long double man(pair<long double, long double> a, pair<long double, long double> b) {
    return abs(a.first-b.first) + abs(a.second-b.second);
}
//内分点
pair<long double, long double> internal_division(pair<long double, long double> a, pair<long double, long double> b, long double p) {
    long double x = a.first + (b.first - a.first) * p;
    long double y = a.second + (b.second - a.second) * p;
    return {x, y};
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}

//hh:mm:ss to second
int convert_to_time(string S) {
    ll h = 10*(S[0]-'0') + (S[1]-'0');
    ll m = 10*(S[3]-'0') + (S[4]-'0');
    ll s = 10*(S[6]-'0') + (S[7]-'0');
    
    return h*3600+m*60+s;
}

//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
vector<vector<ll>> floyd(vector<vector<ll>> G) {
    int N = G.size();
    auto dp = G;
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(dp[i][j] > dp[i][k] + dp[k][j] and dp[i][k] != INF and dp[k][j] != INF) {
                    dp[i][j] = dp[i][k] + dp[k][j];
                }
            }
        }
    }
    return dp;
}
//サイクルがあるか判定
bool cycle(const Graph &G, int v, vector<bool> &seen,  vector<bool> &finished) {
    seen[v] = true;    // 行きがけ時に true になる
    for (auto v2 : G[v]) {
        //if (v2 が逆戻りの場合) continue;  // 無向グラフの場合は必要

        // 頂点 v2 がすでに探索済みの場合はスキップ 
        if (finished[v2]) continue;

        // サイクル検出
        if (seen[v2] && !finished[v2]) return true;

        // 頂点 v2 を再帰的に探索
        if (cycle(G, v2, seen, finished)) return true;
    }
    finished[v] = true;  // 帰りがけ時に true になる
    return false;
}

//Union-Find
struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    vector<ll> cnt;
    
    UnionFind(int N) : par(N),
                       cnt(N, 1) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }
    
    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }
    
    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        cnt[ry] += cnt[rx];
    }
    
    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }

    ll num(int x) { //データxと同じ木に属するデータの数を得る
        return cnt[x] = cnt[root(x)];
    }
};
//BIT
struct BIT {
    vector<long long> array;
    const int n;

    BIT(int _n) : array(_n, 0), n(_n) {}

    //a_0 + ... + a_i
    long long sum(int i) {
        long long s = 0;
        while(i >= 0) {
            s += array[i];
            i -= (i+1) & -(i+1);
        }
        return s;
    }
    //a_i + ... + a_j
    long long sum(int i, int j) {
        long long ans_i = sum(i-1);
        long long ans_j = sum(j);
        return ans_j - ans_i;
    }
    //a_i += x
    void add(int i, long long x) {
        while(i < n) {
            array[i] += x;
            i += (i+1) & -(i+1);
        }
    }
};
//セグ木
struct SegTree {
    int n;
    vector<long long> node;

    SegTree(vector<long long> a) {
        int sz = a.size();

        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = min(node[2*i+1], node[2*i+2]);
    }

    long long getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return INF;
        if(a <= l and r <= b) return node[k];

        long long vl = getmin(a, b, 2*k+1, l, (l+r)/2);
        long long vr = getmin(a, b, 2*k+2, (l+r)/2, r);
        return min(vl, vr);
    }
    void update(int i, long long x) {
        i = n-1+i;
        node[i] = x;
        while(i > 0) {
            i = (i-1)/2;
            node[i] = min(node[2*i+1], node[2*i+2]);
        }
    }
};
//遅延セグ木
struct LazySegTree {
    int n;
    vector<ll> node, lazy;

    LazySegTree(vector<ll> a) {
        int sz = a.size();
        
        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = node[2*i+1] + node[2*i+2];
    }

    void eval(int k, int l, int r) {
        if(lazy[k] != 0) {
            node[k] += lazy[k];

            if(r - l > 1) {
                lazy[2*k+1] += lazy[k]/2;
                lazy[2*k+2] += lazy[k]/2;
            }

            lazy[k] = 0;
        }
    }
    //区間[a,b)に値xを加算
    void add(int a, int b, long long x, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        
        eval(k, l, r);

        if(r <= a or b <= l) return;
        if(a <= l and r <= b) {
            lazy[k] += (r-l)*x;
            eval(k, l, r);
        }else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = node[2*k+1] + node[2*k+2];
        }
    }
    //区間[a,b)の和を取得
    ll getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return 0;

        eval(k, l, r);
        if(a <= l and r <= b) return node[k];
        ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
        return vl + vr;
    }
};

template<typename T> struct Backet {
    vector<T> array;
    vector<T> backet;
    int N, M;

    Backet(vector<T> a) {
        array = a;
        N = a.size(), M = ceil(sqrt(N));
        
        backet.resize((N+M-1)/M);
        for(int i = 0; i < N; i++) {
            backet[i/M] += a[i];
        }
    }
    //a_i + ... + a_j
    void add(int i, T x) {
        array[i] += x;
        backet[i/M] += x;
    }
    T getsum(int i, int j) {
        int l = i/M + 1, r = j/M;
        T s = 0;
        if(l > r) {
            REP(k,i,j) s += array[k];
        }else {
            rep(k,i,l*M) s += array[k];
            rep(k,l,r) s += backet[k];
            REP(k,r*M,j) s += array[k];
        }
        return s;
    }
};

void solve() {
}

int main() {
    int N, Q; cin >> N >> Q;
    vi A(N, 0);
    Backet<int> B(A);
    while(Q--) {
        int com, x, y; cin >> com >> x >> y;
        if(com == 0) {
            x--;
            B.add(x, y);
        }else {
            x--, y--;
            cout << B.getsum(x, y) << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 4152
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vvvll = vector<vector<vector<ll>>>;
using vd = vector<double>;
using vvd = vector<vector<double>>;
using vstr = vector<string>;
using vchar = vector<char>;
using vvchar = vector<vector<char>>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using vvvb = vector<vector<vector<bool>>>;
using pii = pair<int,int>;
using pll = pair<long long, long long>;
using Graph = vector<vector<int>>;
using WeightedGraph = vector<vector<pair<int,ll>>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(ll i = (ll)a; i < (ll)b; i++)
#define REP(i, a, b) for (ll i = (ll)a; i <= (ll)b; i++)
#define rrep(i, a, b) for(ll i = (ll)b-1; i >= (ll)a; i--)
#define RREP(i, a, b) for(ll i = (ll)b; i >= (ll)a; i--)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define spa " "
#define mint modint<MOD>

const int inf = 1070000000;
const long long INF = 4500000000000000000;
//const long long MOD = 998244353;
const long long MOD = 1000000007;
const double pi = 3.141592653589793238;
const double eps = (1e-10);
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";

template<typename T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<typename T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template<typename S, typename T> pair<S, T> operator+(pair<S, T> a, pair<S, T> b) {
    pair<S, T> ans;
    ans.first = a.first + b.first;
    ans.second = a.second + b.second;
    return ans;
} 
template<typename T> vector<T> operator+(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size());
    vector<T> c(N);
    for(int i = 0; i < N; i++) {
        if(i >= a.size()) c[i] = b[i];
        else if(i >= b.size()) c[i] = a[i];
        else c[i] = a[i] + b[i];
    }
    return c;
}
template<typename T> vector<T> operator*(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size()), n = min(a.size(), b.size());
    vector<T> c(N, 0);
    for(int i = 0; i < n; i++) {
        c[i] = a[i] * b[i];
    }
    return c;
}

//拡張ユークリッド
ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if(b == 0) {
        x = 1, y = 0;
        return a;
    }

    ll q = a/b;
    ll g = ext_gcd(b, a-q*b, x, y);
    ll z = x-q*y;
    x = y, y = z;
    return g;
}
//mod mにおけるaの逆元. aとmは互いに素.
ll inverse(ll a, ll m) {
    ll x, y;
    ext_gcd(a, m, x, y);
    x = (x+m) % m;
    return x;
}
//modint
template<std::uint_fast64_t mod> struct modint {
    using u64 = std::uint_fast64_t;
    u64 val;

    modint(u64 v = 0) : val(v % mod) {}

    bool operator==(modint other) {
        return val == other.val;
    }
    bool operator<(const modint& other) const {
        return val < other.val;
    }
    // operator> (大なり)
    bool operator>(const modint& other) const {
        return val > other.val;
    }
    modint operator+(modint other) {
        modint<mod> ans;
        ans.val = val + other.val;
        if(ans.val >= mod) ans.val -= mod;
        return ans;
    }
    modint operator-(modint other) {
        modint<mod> ans;
        if(val < other.val) val += mod;
        ans.val = val - other.val;
        return ans;
    }
    modint operator*(modint other) {
        modint<mod> ans;
        ans.val = (val * other.val) % mod;
        return ans;
    }
    modint operator/(modint other) {
        modint<mod> ans;
        ans.val = (val * inverse(other.val, mod)) % mod;
        return ans;
    }
    modint &operator+=(modint other) {
        *this = *this + other;
        return *this;
    }
    modint &operator-=(modint other) {
        *this = *this - other;
        return *this;
    }
    modint &operator*=(modint other) {
        *this = *this * other;
        return *this;
    }
    modint &operator/=(modint other) {
        *this = *this / other;
        return *this;
    }
    modint &operator++() {
        *this += 1;
        return *this;
    }
    modint &operator++(int) {
        ++(*this);
        return *this;
    }
    modint &operator--() {
        *this -= 1;
        return *this;
    }
    modint &operator--(int) {
        --(*this);
        return *this;
    }
};
//modintの入出力
template<std::uint_fast64_t mod> std::ostream& operator<<(std::ostream &os, const modint<mod> &x) {
    // modint の 'val' メンバを出力ストリーム(os)に渡す
    os << x.val;
    return os; // ストリームを返す (チェーンのため)
}
template<std::uint_fast64_t mod> std::istream& operator>>(std::istream& is, modint<mod> &x) {
    // modintが内部で使っているu64型を取得
    using u64 = typename modint<mod>::u64; 
    
    u64 input_value;
    is >> input_value; // (1) istream(cin) から一時変数に値を読み込む
    
    // (2) 読み込んだ値を使って modint を再構築する
    //     modintのコンストラクタが (input_value % mod) を処理してくれる
    x = modint<mod>(input_value); 
    
    return is; // (3) ストリームを返す (チェーンのため)
}
//累乗, x^n
template<typename T> T pow(T x, int n) {
    T ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
//階乗, n!
template<typename T> T fact(T n) {
    if(n == 0) return 1;
    return n * fact(n-1);
}
//nPk
template<typename T> T perm(T n, T k) {
    if(k == 0) return 1;
    return n * perm(n-1, k-1);
}
//nCk
template<typename T> T comb(T n, T k) {
    if(k > n) return 0;
    return perm(n, min(k, n-k))/fact(min(k, n-k));
}
//ord(n)
ll ord(ll n, ll p) {
    int ans = 0;
    while(n % p == 0) {
        n /= p;
        ans++;
    }
    return ans;
}
//ルジャンドルの公式ord(n!)
ll factord(ll n, ll p) {
    ll ans = 0;
    ll q = p, tmp = n;
    while(tmp > 0) {
        tmp = n/q;
        ans += tmp;
        q *= p;
    }
    return ans;
}
//素因数分解, O(√N)
vector<pair<ll,ll>> factorize(ll N) {
    vector<pair<ll,ll>> ans;
    for(ll p = 2; p*p <= N; p++) {
        int ex = 0;
        while(N % p == 0) {
            N /= p;
            ex++;
        }
        if(ex != 0) ans.push_back({p,ex});
    }
    if(N != 1) ans.push_back({N,1});
    return ans;
}
//素数判定
bool isprime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}
//エラトステネスの篩
struct Eratosthenes {
    vector<bool> prime;
    vector<int> minfactor;
    vector<int> mobius;
    vector<ll> euler;

    //コンストラクタ O(NloglogN)
    Eratosthenes(int N) : prime(N+1, true),
                          minfactor(N+1, -1),
                          mobius(N+1, 1),
                          euler(N+1, 1) {
        prime[0] = false;
        prime[1] = false;
        minfactor[1] = 1;
        REP(i,1,N) euler[i] = i;

        for(int p = 2; p <= N; p++) {
            if(!prime[p]) continue;

            minfactor[p] = p;
            mobius[p] = -1;
            euler[p] = p-1;

            for(int q = 2; p*q <= N; q++) {
                prime[p*q] = false;
                if(minfactor[p*q] == -1) minfactor[p*q] = p;
                if(q % p == 0) mobius[p*q] = 0;
                else mobius[p*q] *= -1;
                euler[p*q] = euler[p*q]*(p-1)/p;
            }
        }
    }

    //素因数分解 O(logn)
    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> ans;
        while(n > 1) {
            int p = minfactor[n], exp = 0;
            while(n % p == 0) {
                n /= p;
                exp++;
            }
            ans.push_back({p, exp});
        }
        return ans;
    }
    //約数列挙 O(σ(n))
    vector<int> divisors(int n) {
        vector<int> ans = {1};
        while(n > 1) {
            int p = minfactor[n], d = 1, s = ans.size();
            while(n % p == 0) {
                d *= p;
                for(int i = 0; i < s; i++) {
                    ans.push_back(ans[i]*d);
                }
                n /= p;
            }
        }
        return ans;
    }
    //素数関数 O(n)
    int count(int n) {
        int ans = 0;
        REP(i,2,n) if(prime[i]) ans++;
        return ans;
    }
};
//高速ゼータ変換
template<typename T> void fast_zeta(vector<T> &f) {
    int N = f.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;
        
        for(int k = N/p; k >= 1; k--) {
            f[k] += f[k*p];
        }
    }
}
//高速メビウス変換
template<typename T> void fast_mobius(vector<T> &F) {
    int N = F.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;

        for(int k = 1; k*p <= N; k++) {
            F[k] -= F[k*p];
        }
    }
}
//添字GCD畳み込み
template<typename T> vector<T> gcd_conv(vector<T> &f, vector<T> &g) {
    int N = max(f.size(), g.size());
    vector<T> F(N, 0), G(N, 0), H(N);
    for(int i = 0; i < f.size(); i++) F[i] = f[i];
    for(int i = 0; i < g.size(); i++) G[i] = g[i];
    fast_zeta(F);
    fast_zeta(G);
    
    for(int i = 0; i < N; i++) H[i] = F[i]*G[i];
    fast_mobius(H);
    
    return H;
}

//行列積
template<typename T> vector<vector<T>> matrix_product(vector<vector<T>> A, vector<vector<T>> B) {
    int H = A.size(), W = A[0].size(), P = B.size(), Q = B[0].size();
    if(W != P) {
        cout << "matrix_size_error" << "\n";
        return vector<vector<T>>(0);
    }

    vector<vector<T>> C(H, vector<T>(Q, 0));
    rep(i,0,H) rep(j,0,Q) {
        rep(k,0,W) {
            C[i][j] += A[i][k]*B[k][j];
        }
    }
    return C;
}
//行列累乗
template<typename T> vector<vector<T>> matrix_pow(vector<vector<T>> A, ll n) {
    int N = A.size();
    vector<vector<T>> ans(N, vector<T>(N, 0));
    rep(i,0,N) ans[i][i] = 1;
    
    while(n > 0) {
        if(n & 1) ans = matrix_product(ans, A);
        A = matrix_product(A, A);
        n >>= 1; 
    }
    return ans;
}

//1+2+...+n = n(n+1)/2
ll tri(ll n) {
    ll x = n*(n+1);
    return x/2;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転, 左回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
long double dist(pair<long double, long double> a, pair<long double, long double> b) {
    return sqrt((a.first-b.first)*(a.first-b.first) + (a.second-b.second)*(a.second-b.second));
}
long double man(pair<long double, long double> a, pair<long double, long double> b) {
    return abs(a.first-b.first) + abs(a.second-b.second);
}
//内分点
pair<long double, long double> internal_division(pair<long double, long double> a, pair<long double, long double> b, long double p) {
    long double x = a.first + (b.first - a.first) * p;
    long double y = a.second + (b.second - a.second) * p;
    return {x, y};
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}

//hh:mm:ss to second
int convert_to_time(string S) {
    ll h = 10*(S[0]-'0') + (S[1]-'0');
    ll m = 10*(S[3]-'0') + (S[4]-'0');
    ll s = 10*(S[6]-'0') + (S[7]-'0');
    
    return h*3600+m*60+s;
}

//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
vector<vector<ll>> floyd(vector<vector<ll>> G) {
    int N = G.size();
    auto dp = G;
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(dp[i][j] > dp[i][k] + dp[k][j] and dp[i][k] != INF and dp[k][j] != INF) {
                    dp[i][j] = dp[i][k] + dp[k][j];
                }
            }
        }
    }
    return dp;
}
//サイクルがあるか判定
bool cycle(const Graph &G, int v, vector<bool> &seen,  vector<bool> &finished) {
    seen[v] = true;    // 行きがけ時に true になる
    for (auto v2 : G[v]) {
        //if (v2 が逆戻りの場合) continue;  // 無向グラフの場合は必要

        // 頂点 v2 がすでに探索済みの場合はスキップ 
        if (finished[v2]) continue;

        // サイクル検出
        if (seen[v2] && !finished[v2]) return true;

        // 頂点 v2 を再帰的に探索
        if (cycle(G, v2, seen, finished)) return true;
    }
    finished[v] = true;  // 帰りがけ時に true になる
    return false;
}

//Union-Find
struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    vector<ll> cnt;
    
    UnionFind(int N) : par(N),
                       cnt(N, 1) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }
    
    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }
    
    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        cnt[ry] += cnt[rx];
    }
    
    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }

    ll num(int x) { //データxと同じ木に属するデータの数を得る
        return cnt[x] = cnt[root(x)];
    }
};
//BIT, 1-indexedに注意！！！！
struct BIT {
    vector<long long> array;
    const int n;

    BIT(int _n) : array(_n, 0), n(_n) {}

    //a_0 + ... + a_i
    long long sum(int i) {
        long long s = 0;
        while(i >= 0) {
            s += array[i];
            i -= (i+1) & -(i+1);
        }
        return s;
    }
    //a_i + ... + a_j
    long long sum(int i, int j) {
        long long ans_i = sum(i-1);
        long long ans_j = sum(j);
        return ans_j - ans_i;
    }
    //a_i += x
    void add(int i, long long x) {
        while(i < n) {
            array[i] += x;
            i += (i+1) & -(i+1);
        }
    }
};
//セグ木
struct SegTree {
    int n;
    vector<long long> node;

    SegTree(vector<long long> a) {
        int sz = a.size();

        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = min(node[2*i+1], node[2*i+2]);
    }

    long long getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return INF;
        if(a <= l and r <= b) return node[k];

        long long vl = getmin(a, b, 2*k+1, l, (l+r)/2);
        long long vr = getmin(a, b, 2*k+2, (l+r)/2, r);
        return min(vl, vr);
    }
    void update(int i, long long x) {
        i = n-1+i;
        node[i] = x;
        while(i > 0) {
            i = (i-1)/2;
            node[i] = min(node[2*i+1], node[2*i+2]);
        }
    }
};
//遅延セグ木
struct LazySegTree {
    int n;
    vector<ll> node, lazy;

    LazySegTree(vector<ll> a) {
        int sz = a.size();
        
        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = node[2*i+1] + node[2*i+2];
    }

    void eval(int k, int l, int r) {
        if(lazy[k] != 0) {
            node[k] += lazy[k];

            if(r - l > 1) {
                lazy[2*k+1] += lazy[k]/2;
                lazy[2*k+2] += lazy[k]/2;
            }

            lazy[k] = 0;
        }
    }
    //区間[a,b)に値xを加算
    void add(int a, int b, long long x, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        
        eval(k, l, r);

        if(r <= a or b <= l) return;
        if(a <= l and r <= b) {
            lazy[k] += (r-l)*x;
            eval(k, l, r);
        }else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = node[2*k+1] + node[2*k+2];
        }
    }
    //区間[a,b)の和を取得
    ll getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return 0;

        eval(k, l, r);
        if(a <= l and r <= b) return node[k];
        ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
        return vl + vr;
    }
};

void solve() {
}

int main() {
    int N, Q; cin >> N >> Q;
    BIT tree(N);
    while(Q--) {
        int com, x, y; cin >> com >> x >> y;
        if(com == 0) {
            x--;
            tree.add(x, y);
        }else {
            x--; y--;
            cout << tree.sum(x, y) << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3892
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vvvll = vector<vector<vector<ll>>>;
using vd = vector<double>;
using vvd = vector<vector<double>>;
using vstr = vector<string>;
using vchar = vector<char>;
using vvchar = vector<vector<char>>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using vvvb = vector<vector<vector<bool>>>;
using pii = pair<int,int>;
using pll = pair<long long, long long>;
using Graph = vector<vector<int>>;
using WeightedGraph = vector<vector<pair<int,ll>>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(ll i = (ll)a; i < (ll)b; i++)
#define REP(i, a, b) for (ll i = (ll)a; i <= (ll)b; i++)
#define rrep(i, a, b) for(ll i = (ll)b-1; i >= (ll)a; i--)
#define RREP(i, a, b) for(ll i = (ll)b; i >= (ll)a; i--)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define spa " "
#define mint modint<MOD>

const int inf = 1070000000;
const long long INF = 4500000000000000000;
//const long long MOD = 998244353;
const long long MOD = 1000000007;
const double pi = 3.141592653589793238;
const double eps = (1e-10);
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";

template<typename T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<typename T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template<typename S, typename T> pair<S, T> operator+(pair<S, T> a, pair<S, T> b) {
    pair<S, T> ans;
    ans.first = a.first + b.first;
    ans.second = a.second + b.second;
    return ans;
} 
template<typename T> vector<T> operator+(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size());
    vector<T> c(N);
    for(int i = 0; i < N; i++) {
        if(i >= a.size()) c[i] = b[i];
        else if(i >= b.size()) c[i] = a[i];
        else c[i] = a[i] + b[i];
    }
    return c;
}
template<typename T> vector<T> operator*(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size()), n = min(a.size(), b.size());
    vector<T> c(N, 0);
    for(int i = 0; i < n; i++) {
        c[i] = a[i] * b[i];
    }
    return c;
}

//拡張ユークリッド
ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if(b == 0) {
        x = 1, y = 0;
        return a;
    }

    ll q = a/b;
    ll g = ext_gcd(b, a-q*b, x, y);
    ll z = x-q*y;
    x = y, y = z;
    return g;
}
//mod mにおけるaの逆元. aとmは互いに素.
ll inverse(ll a, ll m) {
    ll x, y;
    ext_gcd(a, m, x, y);
    x = (x+m) % m;
    return x;
}
//modint
template<std::uint_fast64_t mod> struct modint {
    using u64 = std::uint_fast64_t;
    u64 val;

    modint(u64 v = 0) : val(v % mod) {}

    bool operator==(modint other) {
        return val == other.val;
    }
    bool operator<(const modint& other) const {
        return val < other.val;
    }
    // operator> (大なり)
    bool operator>(const modint& other) const {
        return val > other.val;
    }
    modint operator+(modint other) {
        modint<mod> ans;
        ans.val = val + other.val;
        if(ans.val >= mod) ans.val -= mod;
        return ans;
    }
    modint operator-(modint other) {
        modint<mod> ans;
        if(val < other.val) val += mod;
        ans.val = val - other.val;
        return ans;
    }
    modint operator*(modint other) {
        modint<mod> ans;
        ans.val = (val * other.val) % mod;
        return ans;
    }
    modint operator/(modint other) {
        modint<mod> ans;
        ans.val = (val * inverse(other.val, mod)) % mod;
        return ans;
    }
    modint &operator+=(modint other) {
        *this = *this + other;
        return *this;
    }
    modint &operator-=(modint other) {
        *this = *this - other;
        return *this;
    }
    modint &operator*=(modint other) {
        *this = *this * other;
        return *this;
    }
    modint &operator/=(modint other) {
        *this = *this / other;
        return *this;
    }
    modint &operator++() {
        *this += 1;
        return *this;
    }
    modint &operator++(int) {
        ++(*this);
        return *this;
    }
    modint &operator--() {
        *this -= 1;
        return *this;
    }
    modint &operator--(int) {
        --(*this);
        return *this;
    }
};
//modintの入出力
template<std::uint_fast64_t mod> std::ostream& operator<<(std::ostream &os, const modint<mod> &x) {
    // modint の 'val' メンバを出力ストリーム(os)に渡す
    os << x.val;
    return os; // ストリームを返す (チェーンのため)
}
template<std::uint_fast64_t mod> std::istream& operator>>(std::istream& is, modint<mod> &x) {
    // modintが内部で使っているu64型を取得
    using u64 = typename modint<mod>::u64; 
    
    u64 input_value;
    is >> input_value; // (1) istream(cin) から一時変数に値を読み込む
    
    // (2) 読み込んだ値を使って modint を再構築する
    //     modintのコンストラクタが (input_value % mod) を処理してくれる
    x = modint<mod>(input_value); 
    
    return is; // (3) ストリームを返す (チェーンのため)
}
//累乗, x^n
template<typename T> T pow(T x, int n) {
    T ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
//階乗, n!
template<typename T> T fact(T n) {
    if(n == 0) return 1;
    return n * fact(n-1);
}
//nPk
template<typename T> T perm(T n, T k) {
    if(k == 0) return 1;
    return n * perm(n-1, k-1);
}
//nCk
template<typename T> T comb(T n, T k) {
    if(k > n) return 0;
    return perm(n, min(k, n-k))/fact(min(k, n-k));
}
//ord(n)
ll ord(ll n, ll p) {
    int ans = 0;
    while(n % p == 0) {
        n /= p;
        ans++;
    }
    return ans;
}
//ルジャンドルの公式ord(n!)
ll factord(ll n, ll p) {
    ll ans = 0;
    ll q = p, tmp = n;
    while(tmp > 0) {
        tmp = n/q;
        ans += tmp;
        q *= p;
    }
    return ans;
}
//素因数分解, O(√N)
vector<pair<ll,ll>> factorize(ll N) {
    vector<pair<ll,ll>> ans;
    for(ll p = 2; p*p <= N; p++) {
        int ex = 0;
        while(N % p == 0) {
            N /= p;
            ex++;
        }
        if(ex != 0) ans.push_back({p,ex});
    }
    if(N != 1) ans.push_back({N,1});
    return ans;
}
//素数判定
bool isprime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}
//エラトステネスの篩
struct Eratosthenes {
    vector<bool> prime;
    vector<int> minfactor;
    vector<int> mobius;
    vector<ll> euler;

    //コンストラクタ O(NloglogN)
    Eratosthenes(int N) : prime(N+1, true),
                          minfactor(N+1, -1),
                          mobius(N+1, 1),
                          euler(N+1, 1) {
        prime[0] = false;
        prime[1] = false;
        minfactor[1] = 1;
        REP(i,1,N) euler[i] = i;

        for(int p = 2; p <= N; p++) {
            if(!prime[p]) continue;

            minfactor[p] = p;
            mobius[p] = -1;
            euler[p] = p-1;

            for(int q = 2; p*q <= N; q++) {
                prime[p*q] = false;
                if(minfactor[p*q] == -1) minfactor[p*q] = p;
                if(q % p == 0) mobius[p*q] = 0;
                else mobius[p*q] *= -1;
                euler[p*q] = euler[p*q]*(p-1)/p;
            }
        }
    }

    //素因数分解 O(logn)
    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> ans;
        while(n > 1) {
            int p = minfactor[n], exp = 0;
            while(n % p == 0) {
                n /= p;
                exp++;
            }
            ans.push_back({p, exp});
        }
        return ans;
    }
    //約数列挙 O(σ(n))
    vector<int> divisors(int n) {
        vector<int> ans = {1};
        while(n > 1) {
            int p = minfactor[n], d = 1, s = ans.size();
            while(n % p == 0) {
                d *= p;
                for(int i = 0; i < s; i++) {
                    ans.push_back(ans[i]*d);
                }
                n /= p;
            }
        }
        return ans;
    }
    //素数関数 O(n)
    int count(int n) {
        int ans = 0;
        REP(i,2,n) if(prime[i]) ans++;
        return ans;
    }
};
//高速ゼータ変換
template<typename T> void fast_zeta(vector<T> &f) {
    int N = f.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;
        
        for(int k = N/p; k >= 1; k--) {
            f[k] += f[k*p];
        }
    }
}
//高速メビウス変換
template<typename T> void fast_mobius(vector<T> &F) {
    int N = F.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;

        for(int k = 1; k*p <= N; k++) {
            F[k] -= F[k*p];
        }
    }
}
//添字GCD畳み込み
template<typename T> vector<T> gcd_conv(vector<T> &f, vector<T> &g) {
    int N = max(f.size(), g.size());
    vector<T> F(N, 0), G(N, 0), H(N);
    for(int i = 0; i < f.size(); i++) F[i] = f[i];
    for(int i = 0; i < g.size(); i++) G[i] = g[i];
    fast_zeta(F);
    fast_zeta(G);
    
    for(int i = 0; i < N; i++) H[i] = F[i]*G[i];
    fast_mobius(H);
    
    return H;
}

//行列積
template<typename T> vector<vector<T>> matrix_product(vector<vector<T>> A, vector<vector<T>> B) {
    int H = A.size(), W = A[0].size(), P = B.size(), Q = B[0].size();
    if(W != P) {
        cout << "matrix_size_error" << "\n";
        return vector<vector<T>>(0);
    }

    vector<vector<T>> C(H, vector<T>(Q, 0));
    rep(i,0,H) rep(j,0,Q) {
        rep(k,0,W) {
            C[i][j] += A[i][k]*B[k][j];
        }
    }
    return C;
}
//行列累乗
template<typename T> vector<vector<T>> matrix_pow(vector<vector<T>> A, ll n) {
    int N = A.size();
    vector<vector<T>> ans(N, vector<T>(N, 0));
    rep(i,0,N) ans[i][i] = 1;
    
    while(n > 0) {
        if(n & 1) ans = matrix_product(ans, A);
        A = matrix_product(A, A);
        n >>= 1; 
    }
    return ans;
}

//1+2+...+n = n(n+1)/2
ll tri(ll n) {
    ll x = n*(n+1);
    return x/2;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転, 左回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
long double dist(pair<long double, long double> a, pair<long double, long double> b) {
    return sqrt((a.first-b.first)*(a.first-b.first) + (a.second-b.second)*(a.second-b.second));
}
long double man(pair<long double, long double> a, pair<long double, long double> b) {
    return abs(a.first-b.first) + abs(a.second-b.second);
}
//内分点
pair<long double, long double> internal_division(pair<long double, long double> a, pair<long double, long double> b, long double p) {
    long double x = a.first + (b.first - a.first) * p;
    long double y = a.second + (b.second - a.second) * p;
    return {x, y};
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}

//hh:mm:ss to second
int convert_to_time(string S) {
    ll h = 10*(S[0]-'0') + (S[1]-'0');
    ll m = 10*(S[3]-'0') + (S[4]-'0');
    ll s = 10*(S[6]-'0') + (S[7]-'0');
    
    return h*3600+m*60+s;
}

//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
vector<vector<ll>> floyd(vector<vector<ll>> G) {
    int N = G.size();
    auto dp = G;
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(dp[i][j] > dp[i][k] + dp[k][j] and dp[i][k] != INF and dp[k][j] != INF) {
                    dp[i][j] = dp[i][k] + dp[k][j];
                }
            }
        }
    }
    return dp;
}
//サイクルがあるか判定
bool cycle(const Graph &G, int v, vector<bool> &seen,  vector<bool> &finished) {
    seen[v] = true;    // 行きがけ時に true になる
    for (auto v2 : G[v]) {
        //if (v2 が逆戻りの場合) continue;  // 無向グラフの場合は必要

        // 頂点 v2 がすでに探索済みの場合はスキップ 
        if (finished[v2]) continue;

        // サイクル検出
        if (seen[v2] && !finished[v2]) return true;

        // 頂点 v2 を再帰的に探索
        if (cycle(G, v2, seen, finished)) return true;
    }
    finished[v] = true;  // 帰りがけ時に true になる
    return false;
}

//Union-Find
struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    vector<ll> cnt;
    
    UnionFind(int N) : par(N),
                       cnt(N, 1) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }
    
    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }
    
    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        cnt[ry] += cnt[rx];
    }
    
    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }

    ll num(int x) { //データxと同じ木に属するデータの数を得る
        return cnt[x] = cnt[root(x)];
    }
};
//BIT, 1-indexedに注意！！！！
struct BIT {
    vector<long long> array;
    const int n;

    BIT(int _n) : array(_n+1, 0), n(_n) {}

    //a_1 + ... + a_i
    long long sum(int i) {
        long long s = 0;
        while(i > 0) {
            s += array[i];
            i -= i & -i;
        }
        return s;
    }
    //a_i + ... + a_j
    long long sum(int i, int j) {
        long long ans_i = sum(i-1);
        long long ans_j = sum(j);
        return ans_j - ans_i;
    }
    //a_i += x
    void add(int i, long long x) {
        while(i <= n) {
            array[i] += x;
            i += i & -i;
        }
    }
};
//セグ木
struct SegTree {
    int n;
    vector<long long> node;

    SegTree(vector<long long> a) {
        int sz = a.size();

        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = min(node[2*i+1], node[2*i+2]);
    }

    long long getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return INF;
        if(a <= l and r <= b) return node[k];

        long long vl = getmin(a, b, 2*k+1, l, (l+r)/2);
        long long vr = getmin(a, b, 2*k+2, (l+r)/2, r);
        return min(vl, vr);
    }
    void update(int i, long long x) {
        i = n-1+i;
        node[i] = x;
        while(i > 0) {
            i = (i-1)/2;
            node[i] = min(node[2*i+1], node[2*i+2]);
        }
    }
};
//遅延セグ木
struct LazySegTree {
    int n;
    vector<ll> node, lazy;

    LazySegTree(vector<ll> a) {
        int sz = a.size();
        
        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = node[2*i+1] + node[2*i+2];
    }

    void eval(int k, int l, int r) {
        if(lazy[k] != 0) {
            node[k] += lazy[k];

            if(r - l > 1) {
                lazy[2*k+1] += lazy[k]/2;
                lazy[2*k+2] += lazy[k]/2;
            }

            lazy[k] = 0;
        }
    }
    //区間[a,b)に値xを加算
    void add(int a, int b, long long x, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        
        eval(k, l, r);

        if(r <= a or b <= l) return;
        if(a <= l and r <= b) {
            lazy[k] += (r-l)*x;
            eval(k, l, r);
        }else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = node[2*k+1] + node[2*k+2];
        }
    }
    //区間[a,b)の和を取得
    ll getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return 0;

        eval(k, l, r);
        if(a <= l and r <= b) return node[k];
        ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
        return vl + vr;
    }
};

void solve() {
}

int main() {
    int N, Q; cin >> N >> Q;
    int M = ceil(sqrt(N));
    vi A(N, 0), B((N+M-1)/M, 0);
    while(Q--) {
        int com, x, y; cin >> com >> x >> y;
        if(com == 0) {
            x--;
            A[x] += y;
            B[x/M] += y;
        }else {
            x--, y--;
            int l = x/M, r = y/M, ans = 0;
            l++;
            if(l <= r) {
                rep(i,x,l*M) ans += A[i];
                rep(i,l,r) ans += B[i];
                rep(i,r*M,y+1) ans += A[i];
            }else {
                rep(i,x,y+1) ans += A[i];
            }
            cout << ans << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3512
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vvvll = vector<vector<vector<ll>>>;
using vd = vector<double>;
using vvd = vector<vector<double>>;
using vstr = vector<string>;
using vchar = vector<char>;
using vvchar = vector<vector<char>>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using vvvb = vector<vector<vector<bool>>>;
using pii = pair<int,int>;
using pll = pair<long long, long long>;
using Graph = vector<vector<int>>;
using WeightedGraph = vector<vector<pair<int,ll>>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(ll i = (ll)a; i < (ll)b; i++)
#define REP(i, a, b) for (ll i = (ll)a; i <= (ll)b; i++)
#define rrep(i, a, b) for(ll i = (ll)b-1; i >= (ll)a; i--)
#define RREP(i, a, b) for(ll i = (ll)b; i >= (ll)a; i--)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define spa " "
#define mint modint<MOD>

const int inf = 1070000000;
const long long INF = 4500000000000000000;
//const long long MOD = 998244353;
const long long MOD = 1000000007;
const double pi = 3.141592653589793238;
const double eps = (1e-10);
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";

template<typename T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<typename T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template<typename S, typename T> pair<S, T> operator+(pair<S, T> a, pair<S, T> b) {
    pair<S, T> ans;
    ans.first = a.first + b.first;
    ans.second = a.second + b.second;
    return ans;
} 
template<typename T> vector<T> operator+(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size());
    vector<T> c(N);
    for(int i = 0; i < N; i++) {
        if(i >= a.size()) c[i] = b[i];
        else if(i >= b.size()) c[i] = a[i];
        else c[i] = a[i] + b[i];
    }
    return c;
}
template<typename T> vector<T> operator*(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size()), n = min(a.size(), b.size());
    vector<T> c(N, 0);
    for(int i = 0; i < n; i++) {
        c[i] = a[i] * b[i];
    }
    return c;
}

//拡張ユークリッド
ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if(b == 0) {
        x = 1, y = 0;
        return a;
    }

    ll q = a/b;
    ll g = ext_gcd(b, a-q*b, x, y);
    ll z = x-q*y;
    x = y, y = z;
    return g;
}
//mod mにおけるaの逆元. aとmは互いに素.
ll inverse(ll a, ll m) {
    ll x, y;
    ext_gcd(a, m, x, y);
    x = (x+m) % m;
    return x;
}
//modint
template<std::uint_fast64_t mod> struct modint {
    using u64 = std::uint_fast64_t;
    u64 val;

    modint(u64 v = 0) : val(v % mod) {}

    bool operator==(modint other) {
        return val == other.val;
    }
    bool operator<(const modint& other) const {
        return val < other.val;
    }
    // operator> (大なり)
    bool operator>(const modint& other) const {
        return val > other.val;
    }
    modint operator+(modint other) {
        modint<mod> ans;
        ans.val = val + other.val;
        if(ans.val >= mod) ans.val -= mod;
        return ans;
    }
    modint operator-(modint other) {
        modint<mod> ans;
        if(val < other.val) val += mod;
        ans.val = val - other.val;
        return ans;
    }
    modint operator*(modint other) {
        modint<mod> ans;
        ans.val = (val * other.val) % mod;
        return ans;
    }
    modint operator/(modint other) {
        modint<mod> ans;
        ans.val = (val * inverse(other.val, mod)) % mod;
        return ans;
    }
    modint &operator+=(modint other) {
        *this = *this + other;
        return *this;
    }
    modint &operator-=(modint other) {
        *this = *this - other;
        return *this;
    }
    modint &operator*=(modint other) {
        *this = *this * other;
        return *this;
    }
    modint &operator/=(modint other) {
        *this = *this / other;
        return *this;
    }
    modint &operator++() {
        *this += 1;
        return *this;
    }
    modint &operator++(int) {
        ++(*this);
        return *this;
    }
    modint &operator--() {
        *this -= 1;
        return *this;
    }
    modint &operator--(int) {
        --(*this);
        return *this;
    }
};
//modintの入出力
template<std::uint_fast64_t mod> std::ostream& operator<<(std::ostream &os, const modint<mod> &x) {
    // modint の 'val' メンバを出力ストリーム(os)に渡す
    os << x.val;
    return os; // ストリームを返す (チェーンのため)
}
template<std::uint_fast64_t mod> std::istream& operator>>(std::istream& is, modint<mod> &x) {
    // modintが内部で使っているu64型を取得
    using u64 = typename modint<mod>::u64; 
    
    u64 input_value;
    is >> input_value; // (1) istream(cin) から一時変数に値を読み込む
    
    // (2) 読み込んだ値を使って modint を再構築する
    //     modintのコンストラクタが (input_value % mod) を処理してくれる
    x = modint<mod>(input_value); 
    
    return is; // (3) ストリームを返す (チェーンのため)
}
//累乗, x^n
template<typename T> T pow(T x, int n) {
    T ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
//階乗, n!
template<typename T> T fact(T n) {
    if(n == 0) return 1;
    return n * fact(n-1);
}
//nPk
template<typename T> T perm(T n, T k) {
    if(k == 0) return 1;
    return n * perm(n-1, k-1);
}
//nCk
template<typename T> T comb(T n, T k) {
    if(k > n) return 0;
    return perm(n, min(k, n-k))/fact(min(k, n-k));
}
//ord(n)
ll ord(ll n, ll p) {
    int ans = 0;
    while(n % p == 0) {
        n /= p;
        ans++;
    }
    return ans;
}
//ルジャンドルの公式ord(n!)
ll factord(ll n, ll p) {
    ll ans = 0;
    ll q = p, tmp = n;
    while(tmp > 0) {
        tmp = n/q;
        ans += tmp;
        q *= p;
    }
    return ans;
}
//素因数分解, O(√N)
vector<pair<ll,ll>> factorize(ll N) {
    vector<pair<ll,ll>> ans;
    for(ll p = 2; p*p <= N; p++) {
        int ex = 0;
        while(N % p == 0) {
            N /= p;
            ex++;
        }
        if(ex != 0) ans.push_back({p,ex});
    }
    if(N != 1) ans.push_back({N,1});
    return ans;
}
//素数判定
bool isprime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}
//エラトステネスの篩
struct Eratosthenes {
    vector<bool> prime;
    vector<int> minfactor;
    vector<int> mobius;
    vector<ll> euler;

    //コンストラクタ O(NloglogN)
    Eratosthenes(int N) : prime(N+1, true),
                          minfactor(N+1, -1),
                          mobius(N+1, 1),
                          euler(N+1, 1) {
        prime[0] = false;
        prime[1] = false;
        minfactor[1] = 1;
        REP(i,1,N) euler[i] = i;

        for(int p = 2; p <= N; p++) {
            if(!prime[p]) continue;

            minfactor[p] = p;
            mobius[p] = -1;
            euler[p] = p-1;

            for(int q = 2; p*q <= N; q++) {
                prime[p*q] = false;
                if(minfactor[p*q] == -1) minfactor[p*q] = p;
                if(q % p == 0) mobius[p*q] = 0;
                else mobius[p*q] *= -1;
                euler[p*q] = euler[p*q]*(p-1)/p;
            }
        }
    }

    //素因数分解 O(logn)
    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> ans;
        while(n > 1) {
            int p = minfactor[n], exp = 0;
            while(n % p == 0) {
                n /= p;
                exp++;
            }
            ans.push_back({p, exp});
        }
        return ans;
    }
    //約数列挙 O(σ(n))
    vector<int> divisors(int n) {
        vector<int> ans = {1};
        while(n > 1) {
            int p = minfactor[n], d = 1, s = ans.size();
            while(n % p == 0) {
                d *= p;
                for(int i = 0; i < s; i++) {
                    ans.push_back(ans[i]*d);
                }
                n /= p;
            }
        }
        return ans;
    }
    //素数関数 O(n)
    int count(int n) {
        int ans = 0;
        REP(i,2,n) if(prime[i]) ans++;
        return ans;
    }
};
//高速ゼータ変換
template<typename T> void fast_zeta(vector<T> &f) {
    int N = f.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;
        
        for(int k = N/p; k >= 1; k--) {
            f[k] += f[k*p];
        }
    }
}
//高速メビウス変換
template<typename T> void fast_mobius(vector<T> &F) {
    int N = F.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;

        for(int k = 1; k*p <= N; k++) {
            F[k] -= F[k*p];
        }
    }
}
//添字GCD畳み込み
template<typename T> vector<T> gcd_conv(vector<T> &f, vector<T> &g) {
    int N = max(f.size(), g.size());
    vector<T> F(N, 0), G(N, 0), H(N);
    for(int i = 0; i < f.size(); i++) F[i] = f[i];
    for(int i = 0; i < g.size(); i++) G[i] = g[i];
    fast_zeta(F);
    fast_zeta(G);
    
    for(int i = 0; i < N; i++) H[i] = F[i]*G[i];
    fast_mobius(H);
    
    return H;
}

//行列積
template<typename T> vector<vector<T>> matrix_product(vector<vector<T>> A, vector<vector<T>> B) {
    int H = A.size(), W = A[0].size(), P = B.size(), Q = B[0].size();
    if(W != P) {
        cout << "matrix_size_error" << "\n";
        return vector<vector<T>>(0);
    }

    vector<vector<T>> C(H, vector<T>(Q, 0));
    rep(i,0,H) rep(j,0,Q) {
        rep(k,0,W) {
            C[i][j] += A[i][k]*B[k][j];
        }
    }
    return C;
}
//行列累乗
template<typename T> vector<vector<T>> matrix_pow(vector<vector<T>> A, ll n) {
    int N = A.size();
    vector<vector<T>> ans(N, vector<T>(N, 0));
    rep(i,0,N) ans[i][i] = 1;
    
    while(n > 0) {
        if(n & 1) ans = matrix_product(ans, A);
        A = matrix_product(A, A);
        n >>= 1; 
    }
    return ans;
}

//1+2+...+n = n(n+1)/2
ll tri(ll n) {
    ll x = n*(n+1);
    return x/2;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転, 左回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
long double dist(pair<long double, long double> a, pair<long double, long double> b) {
    return sqrt((a.first-b.first)*(a.first-b.first) + (a.second-b.second)*(a.second-b.second));
}
long double man(pair<long double, long double> a, pair<long double, long double> b) {
    return abs(a.first-b.first) + abs(a.second-b.second);
}
//内分点
pair<long double, long double> internal_division(pair<long double, long double> a, pair<long double, long double> b, long double p) {
    long double x = a.first + (b.first - a.first) * p;
    long double y = a.second + (b.second - a.second) * p;
    return {x, y};
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}

//hh:mm:ss to second
int convert_to_time(string S) {
    ll h = 10*(S[0]-'0') + (S[1]-'0');
    ll m = 10*(S[3]-'0') + (S[4]-'0');
    ll s = 10*(S[6]-'0') + (S[7]-'0');
    
    return h*3600+m*60+s;
}

//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
vector<vector<ll>> floyd(vector<vector<ll>> G) {
    int N = G.size();
    auto dp = G;
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(dp[i][j] > dp[i][k] + dp[k][j] and dp[i][k] != INF and dp[k][j] != INF) {
                    dp[i][j] = dp[i][k] + dp[k][j];
                }
            }
        }
    }
    return dp;
}
//サイクルがあるか判定
bool cycle(const Graph &G, int v, vector<bool> &seen,  vector<bool> &finished) {
    seen[v] = true;    // 行きがけ時に true になる
    for (auto v2 : G[v]) {
        //if (v2 が逆戻りの場合) continue;  // 無向グラフの場合は必要

        // 頂点 v2 がすでに探索済みの場合はスキップ 
        if (finished[v2]) continue;

        // サイクル検出
        if (seen[v2] && !finished[v2]) return true;

        // 頂点 v2 を再帰的に探索
        if (cycle(G, v2, seen, finished)) return true;
    }
    finished[v] = true;  // 帰りがけ時に true になる
    return false;
}

//Union-Find
struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    vector<ll> cnt;
    
    UnionFind(int N) : par(N),
                       cnt(N, 1) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }
    
    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }
    
    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        cnt[ry] += cnt[rx];
    }
    
    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }

    ll num(int x) { //データxと同じ木に属するデータの数を得る
        return cnt[x] = cnt[root(x)];
    }
};
//BIT, 1-indexedに注意！！！！
struct BIT {
    vector<long long> array;
    const int n;

    BIT(int _n) : array(_n+1, 0), n(_n) {}

    //a_1 + ... + a_i
    long long sum(int i) {
        long long s = 0;
        while(i > 0) {
            s += array[i];
            i -= i & -i;
        }
        return s;
    }
    //a_i + ... + a_j
    long long sum(int i, int j) {
        long long ans_i = sum(i-1);
        long long ans_j = sum(j);
        return ans_j - ans_i;
    }
    //a_i += x
    void add(int i, long long x) {
        while(i <= n) {
            array[i] += x;
            i += i & -i;
        }
    }
};
//セグ木
struct SegTree {
    int n;
    vector<long long> node;

    SegTree(vector<long long> a) {
        int sz = a.size();

        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = min(node[2*i+1], node[2*i+2]);
    }

    long long getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return INF;
        if(a <= l and r <= b) return node[k];

        long long vl = getmin(a, b, 2*k+1, l, (l+r)/2);
        long long vr = getmin(a, b, 2*k+2, (l+r)/2, r);
        return min(vl, vr);
    }
    void update(int i, long long x) {
        i = n-1+i;
        node[i] = x;
        while(i > 0) {
            i = (i-1)/2;
            node[i] = min(node[2*i+1], node[2*i+2]);
        }
    }
};
//遅延セグ木
struct LazySegTree {
    int n;
    vector<ll> node, lazy;

    LazySegTree(vector<ll> a) {
        int sz = a.size();
        
        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = node[2*i+1] + node[2*i+2];
    }

    void eval(int k, int l, int r) {
        if(lazy[k] != 0) {
            node[k] += lazy[k];

            if(r - l > 1) {
                lazy[2*k+1] += lazy[k]/2;
                lazy[2*k+2] += lazy[k]/2;
            }

            lazy[k] = 0;
        }
    }
    //区間[a,b)に値xを加算
    void add(int a, int b, long long x, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        
        eval(k, l, r);

        if(r <= a or b <= l) return;
        if(a <= l and r <= b) {
            lazy[k] += (r-l)*x;
            eval(k, l, r);
        }else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = node[2*k+1] + node[2*k+2];
        }
    }
    //区間[a,b)の和を取得
    ll getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return 0;

        eval(k, l, r);
        if(a <= l and r <= b) return node[k];
        ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
        return vl + vr;
    }
};

void solve() {
}

int main() {
    int N, Q; cin >> N >> Q;
    BIT tree(N);
    while(Q--) {
        int com, x, y; cin >> com >> x >> y;
        if(com == 0) {
            tree.add(x, y);
        }
        if(com == 1) {
            cout << tree.sum(x, y) << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3888
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vvvll = vector<vector<vector<ll>>>;
using vd = vector<double>;
using vvd = vector<vector<double>>;
using vstr = vector<string>;
using vchar = vector<char>;
using vvchar = vector<vector<char>>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using vvvb = vector<vector<vector<bool>>>;
using pii = pair<int,int>;
using pll = pair<long long, long long>;
using Graph = vector<vector<int>>;
using WeightedGraph = vector<vector<pair<int,ll>>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(ll i = (ll)a; i < (ll)b; i++)
#define REP(i, a, b) for (ll i = (ll)a; i <= (ll)b; i++)
#define rrep(i, a, b) for(ll i = (ll)b-1; i >= (ll)a; i--)
#define RREP(i, a, b) for(ll i = (ll)b; i >= (ll)a; i--)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define spa " "
#define mint modint<MOD>

const int inf = 1070000000;
const long long INF = 4500000000000000000;
//const long long MOD = 998244353;
const long long MOD = 1000000007;
const double pi = 3.141592653589793238;
const double eps = (1e-10);
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";

template<typename T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<typename T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template<typename S, typename T> pair<S, T> operator+(pair<S, T> a, pair<S, T> b) {
    pair<S, T> ans;
    ans.first = a.first + b.first;
    ans.second = a.second + b.second;
    return ans;
} 
template<typename T> vector<T> operator+(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size());
    vector<T> c(N);
    for(int i = 0; i < N; i++) {
        if(i >= a.size()) c[i] = b[i];
        else if(i >= b.size()) c[i] = a[i];
        else c[i] = a[i] + b[i];
    }
    return c;
}
template<typename T> vector<T> operator*(vector<T> a, vector<T> b) {
    int N = max(a.size(), b.size()), n = min(a.size(), b.size());
    vector<T> c(N, 0);
    for(int i = 0; i < n; i++) {
        c[i] = a[i] * b[i];
    }
    return c;
}

//拡張ユークリッド
ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if(b == 0) {
        x = 1, y = 0;
        return a;
    }

    ll q = a/b;
    ll g = ext_gcd(b, a-q*b, x, y);
    ll z = x-q*y;
    x = y, y = z;
    return g;
}
//mod mにおけるaの逆元. aとmは互いに素.
ll inverse(ll a, ll m) {
    ll x, y;
    ext_gcd(a, m, x, y);
    x = (x+m) % m;
    return x;
}
//modint
template<std::uint_fast64_t mod> struct modint {
    using u64 = std::uint_fast64_t;
    u64 val;

    modint(u64 v = 0) : val(v % mod) {}

    bool operator==(modint other) {
        return val == other.val;
    }
    bool operator<(const modint& other) const {
        return val < other.val;
    }
    // operator> (大なり)
    bool operator>(const modint& other) const {
        return val > other.val;
    }
    modint operator+(modint other) {
        modint<mod> ans;
        ans.val = val + other.val;
        if(ans.val >= mod) ans.val -= mod;
        return ans;
    }
    modint operator-(modint other) {
        modint<mod> ans;
        if(val < other.val) val += mod;
        ans.val = val - other.val;
        return ans;
    }
    modint operator*(modint other) {
        modint<mod> ans;
        ans.val = (val * other.val) % mod;
        return ans;
    }
    modint operator/(modint other) {
        modint<mod> ans;
        ans.val = (val * inverse(other.val, mod)) % mod;
        return ans;
    }
    modint &operator+=(modint other) {
        *this = *this + other;
        return *this;
    }
    modint &operator-=(modint other) {
        *this = *this - other;
        return *this;
    }
    modint &operator*=(modint other) {
        *this = *this * other;
        return *this;
    }
    modint &operator/=(modint other) {
        *this = *this / other;
        return *this;
    }
    modint &operator++() {
        *this += 1;
        return *this;
    }
    modint &operator++(int) {
        ++(*this);
        return *this;
    }
    modint &operator--() {
        *this -= 1;
        return *this;
    }
    modint &operator--(int) {
        --(*this);
        return *this;
    }
};
//modintの入出力
template<std::uint_fast64_t mod> std::ostream& operator<<(std::ostream &os, const modint<mod> &x) {
    // modint の 'val' メンバを出力ストリーム(os)に渡す
    os << x.val;
    return os; // ストリームを返す (チェーンのため)
}
template<std::uint_fast64_t mod> std::istream& operator>>(std::istream& is, modint<mod> &x) {
    // modintが内部で使っているu64型を取得
    using u64 = typename modint<mod>::u64; 
    
    u64 input_value;
    is >> input_value; // (1) istream(cin) から一時変数に値を読み込む
    
    // (2) 読み込んだ値を使って modint を再構築する
    //     modintのコンストラクタが (input_value % mod) を処理してくれる
    x = modint<mod>(input_value); 
    
    return is; // (3) ストリームを返す (チェーンのため)
}
//累乗, x^n
template<typename T> T pow(T x, int n) {
    T ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
//階乗, n!
template<typename T> T fact(T n) {
    if(n == 0) return 1;
    return n * fact(n-1);
}
//nPk
template<typename T> T perm(T n, T k) {
    if(k == 0) return 1;
    return n * perm(n-1, k-1);
}
//nCk
template<typename T> T comb(T n, T k) {
    if(k > n) return 0;
    return perm(n, min(k, n-k))/fact(min(k, n-k));
}
//ord(n)
ll ord(ll n, ll p) {
    int ans = 0;
    while(n % p == 0) {
        n /= p;
        ans++;
    }
    return ans;
}
//ルジャンドルの公式ord(n!)
ll factord(ll n, ll p) {
    ll ans = 0;
    ll q = p, tmp = n;
    while(tmp > 0) {
        tmp = n/q;
        ans += tmp;
        q *= p;
    }
    return ans;
}
//素因数分解, O(√N)
vector<pair<ll,ll>> factorize(ll N) {
    vector<pair<ll,ll>> ans;
    for(ll p = 2; p*p <= N; p++) {
        int ex = 0;
        while(N % p == 0) {
            N /= p;
            ex++;
        }
        if(ex != 0) ans.push_back({p,ex});
    }
    if(N != 1) ans.push_back({N,1});
    return ans;
}
//素数判定
bool isprime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}
//エラトステネスの篩
struct Eratosthenes {
    vector<bool> prime;
    vector<int> minfactor;
    vector<int> mobius;
    vector<ll> euler;

    //コンストラクタ O(NloglogN)
    Eratosthenes(int N) : prime(N+1, true),
                          minfactor(N+1, -1),
                          mobius(N+1, 1),
                          euler(N+1, 1) {
        prime[0] = false;
        prime[1] = false;
        minfactor[1] = 1;
        REP(i,1,N) euler[i] = i;

        for(int p = 2; p <= N; p++) {
            if(!prime[p]) continue;

            minfactor[p] = p;
            mobius[p] = -1;
            euler[p] = p-1;

            for(int q = 2; p*q <= N; q++) {
                prime[p*q] = false;
                if(minfactor[p*q] == -1) minfactor[p*q] = p;
                if(q % p == 0) mobius[p*q] = 0;
                else mobius[p*q] *= -1;
                euler[p*q] = euler[p*q]*(p-1)/p;
            }
        }
    }

    //素因数分解 O(logn)
    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> ans;
        while(n > 1) {
            int p = minfactor[n], exp = 0;
            while(n % p == 0) {
                n /= p;
                exp++;
            }
            ans.push_back({p, exp});
        }
        return ans;
    }
    //約数列挙 O(σ(n))
    vector<int> divisors(int n) {
        vector<int> ans = {1};
        while(n > 1) {
            int p = minfactor[n], d = 1, s = ans.size();
            while(n % p == 0) {
                d *= p;
                for(int i = 0; i < s; i++) {
                    ans.push_back(ans[i]*d);
                }
                n /= p;
            }
        }
        return ans;
    }
    //素数関数 O(n)
    int count(int n) {
        int ans = 0;
        REP(i,2,n) if(prime[i]) ans++;
        return ans;
    }
};
//高速ゼータ変換
template<typename T> void fast_zeta(vector<T> &f) {
    int N = f.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;
        
        for(int k = N/p; k >= 1; k--) {
            f[k] += f[k*p];
        }
    }
}
//高速メビウス変換
template<typename T> void fast_mobius(vector<T> &F) {
    int N = F.size()-1;
    Eratosthenes sieve(N);
    for(int p = 2; p < N; p++) {
        if(!sieve.prime[p]) continue;

        for(int k = 1; k*p <= N; k++) {
            F[k] -= F[k*p];
        }
    }
}
//添字GCD畳み込み
template<typename T> vector<T> gcd_conv(vector<T> &f, vector<T> &g) {
    int N = max(f.size(), g.size());
    vector<T> F(N, 0), G(N, 0), H(N);
    for(int i = 0; i < f.size(); i++) F[i] = f[i];
    for(int i = 0; i < g.size(); i++) G[i] = g[i];
    fast_zeta(F);
    fast_zeta(G);
    
    for(int i = 0; i < N; i++) H[i] = F[i]*G[i];
    fast_mobius(H);
    
    return H;
}

//行列積
template<typename T> vector<vector<T>> matrix_product(vector<vector<T>> A, vector<vector<T>> B) {
    int H = A.size(), W = A[0].size(), P = B.size(), Q = B[0].size();
    if(W != P) {
        cout << "matrix_size_error" << "\n";
        return vector<vector<T>>(0);
    }

    vector<vector<T>> C(H, vector<T>(Q, 0));
    rep(i,0,H) rep(j,0,Q) {
        rep(k,0,W) {
            C[i][j] += A[i][k]*B[k][j];
        }
    }
    return C;
}
//行列累乗
template<typename T> vector<vector<T>> matrix_pow(vector<vector<T>> A, ll n) {
    int N = A.size();
    vector<vector<T>> ans(N, vector<T>(N, 0));
    rep(i,0,N) ans[i][i] = 1;
    
    while(n > 0) {
        if(n & 1) ans = matrix_product(ans, A);
        A = matrix_product(A, A);
        n >>= 1; 
    }
    return ans;
}

//1+2+...+n = n(n+1)/2
ll tri(ll n) {
    ll x = n*(n+1);
    return x/2;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転, 左回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
long double dist(pair<long double, long double> a, pair<long double, long double> b) {
    return sqrt((a.first-b.first)*(a.first-b.first) + (a.second-b.second)*(a.second-b.second));
}
long double man(pair<long double, long double> a, pair<long double, long double> b) {
    return abs(a.first-b.first) + abs(a.second-b.second);
}
//内分点
pair<long double, long double> internal_division(pair<long double, long double> a, pair<long double, long double> b, long double p) {
    long double x = a.first + (b.first - a.first) * p;
    long double y = a.second + (b.second - a.second) * p;
    return {x, y};
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}

//hh:mm:ss to second
int convert_to_time(string S) {
    ll h = 10*(S[0]-'0') + (S[1]-'0');
    ll m = 10*(S[3]-'0') + (S[4]-'0');
    ll s = 10*(S[6]-'0') + (S[7]-'0');
    
    return h*3600+m*60+s;
}

//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
vector<vector<ll>> floyd(vector<vector<ll>> G) {
    int N = G.size();
    auto dp = G;
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(dp[i][j] > dp[i][k] + dp[k][j] and dp[i][k] != INF and dp[k][j] != INF) {
                    dp[i][j] = dp[i][k] + dp[k][j];
                }
            }
        }
    }
    return dp;
}
//サイクルがあるか判定
bool cycle(const Graph &G, int v, vector<bool> &seen,  vector<bool> &finished) {
    seen[v] = true;    // 行きがけ時に true になる
    for (auto v2 : G[v]) {
        //if (v2 が逆戻りの場合) continue;  // 無向グラフの場合は必要

        // 頂点 v2 がすでに探索済みの場合はスキップ 
        if (finished[v2]) continue;

        // サイクル検出
        if (seen[v2] && !finished[v2]) return true;

        // 頂点 v2 を再帰的に探索
        if (cycle(G, v2, seen, finished)) return true;
    }
    finished[v] = true;  // 帰りがけ時に true になる
    return false;
}

//Union-Find
struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    vector<ll> cnt;
    
    UnionFind(int N) : par(N),
                       cnt(N, 1) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }
    
    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }
    
    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        cnt[ry] += cnt[rx];
    }
    
    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }

    ll num(int x) { //データxと同じ木に属するデータの数を得る
        return cnt[x] = cnt[root(x)];
    }
};
//BIT, 1-indexedに注意！！！！
template<typename T> struct BIT {
    vector<T> array;
    const int n;

    BIT(int _n) : array(_n+1, 0), n(_n) {}

    T sum(int i) {
        T s = 0;
        while(i > 0) {
            s += array[i];
            i -= i & -i;
        }
        return s;
    }
    T sum(int i, int j) {
        T ans_i = sum(i-1);
        T ans_j = sum(j);
        return ans_j - ans_i;
    }
    void add(int i, T x) {
        while(i <= n) {
            array[i] += x;
            i += i & -i;
        }
    }
};
//セグ木
struct SegTree {
    int n;
    vector<long long> node;

    SegTree(vector<long long> a) {
        int sz = a.size();

        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = min(node[2*i+1], node[2*i+2]);
    }

    long long getmin(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return INF;
        if(a <= l and r <= b) return node[k];

        long long vl = getmin(a, b, 2*k+1, l, (l+r)/2);
        long long vr = getmin(a, b, 2*k+2, (l+r)/2, r);
        return min(vl, vr);
    }
    void update(int i, long long x) {
        i = n-1+i;
        node[i] = x;
        while(i > 0) {
            i = (i-1)/2;
            node[i] = min(node[2*i+1], node[2*i+2]);
        }
    }
};
//遅延セグ木
struct LazySegTree {
    int n;
    vector<ll> node, lazy;

    LazySegTree(vector<ll> a) {
        int sz = a.size();
        
        n = 1;
        while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i = 0; i < sz; i++) node[n-1+i] = a[i];
        for(int i = n-2; i >= 0; i--) node[i] = node[2*i+1] + node[2*i+2];
    }

    void eval(int k, int l, int r) {
        if(lazy[k] != 0) {
            node[k] += lazy[k];

            if(r - l > 1) {
                lazy[2*k+1] += lazy[k]/2;
                lazy[2*k+2] += lazy[k]/2;
            }

            lazy[k] = 0;
        }
    }
    //区間[a,b)に値xを加算
    void add(int a, int b, long long x, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        
        eval(k, l, r);

        if(r <= a or b <= l) return;
        if(a <= l and r <= b) {
            lazy[k] += (r-l)*x;
            eval(k, l, r);
        }else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = node[2*k+1] + node[2*k+2];
        }
    }
    //区間[a,b)の和を取得
    ll getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
        if(r < 0) r = n;
        if(r <= a or b <= l) return 0;

        eval(k, l, r);
        if(a <= l and r <= b) return node[k];
        ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
        return vl + vr;
    }
};

void solve() {
}

int main() {
    int N, Q; cin >> N >> Q;
    vll A(N, 0);
    LazySegTree seg(A);
    while(Q--) {
        int com, x, y; cin >> com >> x >> y;
        if(com == 0) {
            x--;
            seg.add(x, x+1, y);
        }
        if(com == 1) {
            x--, y--;
            cout << seg.getsum(x, y+1) << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 8596
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#define ll long long
#define rep(i,n,m) for(int i=(int)(n);i < (int)(m); i++)
#define repm(i,n,m) for(int i=(int)(n);i >= (int)(m); i--)
// #define _GLIBCXX_DEBUG
using namespace std;

/*
fa: 値の更新をする際に操作を指定する関数 || ラムダ式で関数を作る || 例: RSQ -> auto fa = [](int &x1, int &x2){ return x1 + x2; }; 
fx: クエリでやる操作を指定する関数 || ラムダ式で関数を作る || 例: RMQ -> auto fx = [](int &x1, int &x2){ return min(x1, x2); }; 
ex: fx の 単位元 || 例: RMQ -> int ex = numeric_limit<int>::max();, RSQ -> int ex = 0;

tips: 関数の引数に & つけるとバグる
*/

template<class X>
struct SegTree{
    using FX = function<X(X, X)>;
    int n;
    FX fx, fa;
    const X ex;
    vector<X> dat;

    SegTree(int n_, FX fa_, FX fx_, X ex_) : n(), fa(fa_), fx(fx_), ex(ex_){
        int x = 1;
        while(x < n_){
            x *= 2;
        }
        n = x;
        dat.resize(2 * n - 1, ex_);
    }

    void set(int i, X val){
        dat[i + n - 1] = val;
    }
    void build(){
        for(int i = n - 2; i >= 0; i--){
            dat[i] = fx(dat[2 * i + 1], dat[2 * i + 2]);
        }
    }

    void update(int i, X val){ // 0-index
        i += n - 1;
        dat[i] = fa(dat[i], val);
        while(i > 0){
            i = (i - 1) / 2;
            dat[i] = fx(dat[2 * i + 1], dat[2 * i + 2]);
        }
    }

    X query(int a, int b){ // 0-index
        return query_sub(a, b, 0, 0, n);
    }
    X query_sub(int a, int b, int k, int l, int r){ // a,b :探索範囲の指定 || k:今調べている dat の idx || l,r: dat[k]の示す範囲
        if(r <= a or b <= l){
            return ex;
        }
        else if(a <= l and r <= b){
            return dat[k];
        }
        else{
            X vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
            X vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
            return fx(vl, vr);
        }
    }
};

int main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    int n,q;
    cin >> n >> q;

    /*
    auto fa = [](int x1, int x2){ return x2; };
    auto fx = [](int x1, int x2){ return min(x1, x2); };
    int ex = numeric_limits<int>::max();
    SegTree<int> RMQ(n, fa, fx, ex);
    */

    auto fa = [](int x1, int x2){ return x1 + x2; };
    auto fx = [](int x1, int x2){ return x1 + x2; };
    int ex = 0;
    SegTree<int> RSQ(n, fa, fx, ex);

    while(q--){
        int op;
        cin >> op;

        if(op == 0){
            int x,y;
            cin >> x >> y;
            x--;
            RSQ.update(x, y);
        }

        if(op == 1){
            int x,y;
            cin >> x >> y;
            x--; y--;
            cout << RSQ.query(x, y + 1) << '\n';
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 4148
final_rank: 2

code_snippet: #define _USE_MATH_DEFINES
#include<bits/stdc++.h>
#define OVERLOAD_REP(v1, v2, v3, v4, NAME, ...) NAME
#define REP1(i, n) for (int i = 0; (i) < (n); ++(i))
#define REP2(i, l, r) for (int i = (l); (i) < (r); ++(i))
#define REP3(i, l, r, d) for (int i = (l); (i) < (r); (i)+=(d))
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_PRE(v1, v2, v3, v4, NAME, ...) NAME
#define PRE1(i, n) for (int i = (n)-1; (i) >= 0; --(i)) // [0,n)
#define PRE2(i, l, r) for (int i = (r)-1; (i) >= (l); --(i)) //[l,r)
#define PRE3(i, l, r, d) for (int i = (r)-1; (i) >= (l); (i)-=(d))
#define pre(...) OVERLOAD_PRE(__VA_ARGS__, PRE3, PRE2, PRE1)(__VA_ARGS__)
#define bg begin()
#define en end()
#define rbg rbegin()
#define ren rend()
#define all(x) x.bg,x.en
#define rall(x) x.rbg,x.ren
#define pf push_front
#define pb push_back
#define eb emplace_back
#define fir first
#define sec second
#define sz(x) ((int)(x).size())
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using sti = stack<int>;
using sei = set<int>;
using qi = queue<int>;
using qii = queue<pii>;
using dqi = deque<int>;
template<class t, class s> using umap = unordered_map<t,s>;
template<class t> using uset = unordered_set<t>;
template<class t> using mset = multiset<t>;
template<class t> using pq=priority_queue<t>;
template<class t> using pqg=priority_queue<t,vector<t>, greater<t>>;
template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;
template<class t> using vvvc=vc<vc<vc<t>>>;
using vi=vc<int>;
using vvi=vc<vc<int>>;
using vll=vc<ll>;
using vvll=vc<vc<ll>>;
using vd=vc<double>;
using vvd=vc<vc<double>>;
using vb=vc<bool>;
using vvb=vc<vc<bool>>;
using vch=vc<char>;
using vs=vc<string>;
const int inf = 1001001001;
const ll infl = 1LL << 60;
const ll mod = 998244353;
template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b; return true;} return false;}
template<class t,class u> bool chmin(t&a,u b){if(a>b){a=b; return true;} return false;}
void yes(){ cout << "Yes" << '\n'; }
void no(){ cout << "No" << '\n'; }

template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
    int _n,size=1,log=0;
    vc<S> d; //1-indexed
	segtree(): segtree(0){}
    segtree(int n): segtree(vc<S>(n,e())){}
	segtree(const vc<S> &v): _n(sz(v)){
        while(_n>size) size<<=1, log++;
		d.assign(2*size,e());
		rep(i,_n) d[size+i]=v[i];
		pre(i,1,size) update(i);
    }
	void update(int k) { d[k]=op(d[2*k], d[2*k+1]); }
    void set(int p, S x){
		assert(0 <= p && p < _n);
		p+=size;
		d[p]=x;
		rep(i,1,log+1) update(p>>i);
	}
	S get(int p) const { 
		assert(0 <= p && p < _n);
		return d[p+size];
	}
	S prod(int l, int r) const {
		assert(0 <= l && l <= r && r <= _n);
		S sml=e(), smr=e();
		l+=size; r+=size;
		while(l<r){
			if(l&1) sml=op(sml,d[l++]);
			if(r&1) smr=op(d[--r],smr);
			l>>=1; r>>=1;
		}
		return op(sml,smr);
	}
	S all_prod() const { return d[1]; }
	
	template <bool (*f)(S)> int max_right(int l, int r) const {
        return min(r, max_right(l, [](S x) { return f(x); }));
    }
	template <bool (*f)(S)> int max_right(int l) const {
        return max_right(l, [](S x) { return f(x); });
    }
	template <class F> int max_right(int l, int r, F f) const {
		return min(r, max_right<F>(l, f));
    }
    template <class F> int max_right(int l, F f) const {
		assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

	template <bool (*f)(S)> int min_left(int l, int r) const {
        return max(l, min_left(r, [](S x) { return f(x); }));
    }
    template <bool (*f)(S)> int min_left(int r) const {
        return min_left(r, [](S x) { return f(x); });
    }
	template <class F> int min_left(int l, int r, F f) const {
		return max(l, min_left<F>(r, f));
	}
    template <class F> int min_left(int r, F f) const {
		assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }
    inline S operator[](int i) { return get(i); }
    /* debug */
    void print() {
        cerr << "print: ";
        rep(i,_n){
            cerr << (*this)[i];
            if(i!=_n) cerr << " ";
        }
        cerr << endl;
    }
};

using S=ll;
S op(S a, S b) { return a+b; }
S e() { return 0; }

int main(){	
	ios::sync_with_stdio(false);
  	cin.tie(0);
	int n,q; cin >> n >> q;
    vll a(n);
	segtree<S,op,e> seg(a);

    rep(i,q){
        int type; cin >> type;
        if(type==0){
            int s,x; cin >> s >> x; s--;
            seg.set(s,seg[s]+x);
        } else {
            int s,t; cin >> s >> t; s--;
            cout << seg.prod(s,t) << endl;
        }
    }
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 5828
final_rank: 14

code_snippet: #define _USE_MATH_DEFINES
#include<bits/stdc++.h>
#define OVERLOAD_REP(v1, v2, v3, v4, NAME, ...) NAME
#define REP1(i, n) for (int i = 0; (i) < (n); ++(i))
#define REP2(i, l, r) for (int i = (l); (i) < (r); ++(i))
#define REP3(i, l, r, d) for (int i = (l); (i) < (r); (i)+=(d))
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_PRE(v1, v2, v3, v4, NAME, ...) NAME
#define PRE1(i, n) for (int i = (n)-1; (i) >= 0; --(i)) // [0,n)
#define PRE2(i, l, r) for (int i = (r)-1; (i) >= (l); --(i)) //[l,r)
#define PRE3(i, l, r, d) for (int i = (r)-1; (i) >= (l); (i)-=(d))
#define pre(...) OVERLOAD_PRE(__VA_ARGS__, PRE3, PRE2, PRE1)(__VA_ARGS__)
#define bg begin()
#define en end()
#define rbg rbegin()
#define ren rend()
#define all(x) x.bg,x.en
#define rall(x) x.rbg,x.ren
#define pf push_front
#define pb push_back
#define eb emplace_back
#define fir first
#define sec second
#define sz(x) ((int)(x).size())
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using sti = stack<int>;
using sei = set<int>;
using qi = queue<int>;
using qii = queue<pii>;
using dqi = deque<int>;
template<class t, class s> using umap = unordered_map<t,s>;
template<class t> using uset = unordered_set<t>;
template<class t> using mset = multiset<t>;
template<class t> using pq=priority_queue<t>;
template<class t> using pqg=priority_queue<t,vector<t>, greater<t>>;
template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;
template<class t> using vvvc=vc<vc<vc<t>>>;
using vi=vc<int>;
using vvi=vc<vc<int>>;
using vll=vc<ll>;
using vvll=vc<vc<ll>>;
using vd=vc<double>;
using vvd=vc<vc<double>>;
using vb=vc<bool>;
using vvb=vc<vc<bool>>;
using vch=vc<char>;
using vs=vc<string>;
const int inf = 1001001001;
const ll infl = 1LL << 60;
const ll mod = 998244353;
template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b; return true;} return false;}
template<class t,class u> bool chmin(t&a,u b){if(a>b){a=b; return true;} return false;}
void yes(){ cout << "Yes" << '\n'; }
void no(){ cout << "No" << '\n'; }

template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
    int _n,size=1,log=0;
    vc<S> d; //1-indexed
	segtree(): segtree(0){}
    segtree(int n): segtree(vc<S>(n,e())){}
	segtree(const vc<S> &v): _n(sz(v)){
        while(_n>size) size<<=1, log++;
		d.assign(2*size,e());
		rep(i,_n) d[size+i]=v[i];
		pre(i,1,size) update(i);
    }
	void update(int k) { d[k]=op(d[2*k], d[2*k+1]); }
    void set(int p, S x){
		assert(0 <= p && p < _n);
		p+=size;
		d[p]=x;
		rep(i,1,log+1) update(p>>i);
	}
	S get(int p) const { 
		assert(0 <= p && p < _n);
		return d[p+size];
	}
	S prod(int l, int r) const {
		assert(0 <= l && l <= r && r <= _n);
		S sml=e(), smr=e();
		l+=size; r+=size;
		while(l<r){
			if(l&1) sml=op(sml,d[l++]);
			if(r&1) smr=op(d[--r],smr);
			l>>=1; r>>=1;
		}
		return op(sml,smr);
	}
	S all_prod() const { return d[1]; }
	
	template <bool (*f)(S)> int max_right(int l, int r) const {
        return min(r, max_right(l, [](S x) { return f(x); }));
    }
	template <bool (*f)(S)> int max_right(int l) const {
        return max_right(l, [](S x) { return f(x); });
    }
	template <class F> int max_right(int l, int r, F f) const {
		return min(r, max_right<F>(l, f));
    }
    template <class F> int max_right(int l, F f) const {
		assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

	template <bool (*f)(S)> int min_left(int l, int r) const {
        return max(l, min_left(r, [](S x) { return f(x); }));
    }
    template <bool (*f)(S)> int min_left(int r) const {
        return min_left(r, [](S x) { return f(x); });
    }
	template <class F> int min_left(int l, int r, F f) const {
		return max(l, min_left<F>(r, f));
	}
    template <class F> int min_left(int r, F f) const {
		assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }
    inline S operator[](int i) { return get(i); }
    /* debug */
    void print() {
        cerr << "print: ";
        rep(i,_n){
            cerr << (*this)[i];
            if(i!=_n) cerr << " ";
        }
        cerr << endl;
    }
};

using S=ll;
S op(S a, S b) { return a+b; }
S e() { return 0; }

int main(){	
	ios::sync_with_stdio(false);
  	cin.tie(0);
	int n,q; cin >> n >> q;
	segtree<S,op,e> seg(n);

	rep(i,q){
		int t; cin >> t;
		if(t==0){
			int x; ll v; cin >> x >> v; x--;
			seg.set(x,seg[x]+v);
		} else {
			int s,t; cin >> s >> t; s--;
			cout << seg.prod(s,t) << "\n";
		}
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 5976
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
int a[1<<17];
int main(){
    int n,q;
    cin >> n >> q;
    auto add=[&](int x,int d){
      for(int i=x;i<(1<<17);i=(i|(i+1)))a[i]+=d;  
    };
    auto suma=[&](int x){
        //1-indexed
        int ans=0;
        for(int i=x;i>0;i=(i&(i-1)))ans+=a[i-1];
        return ans;
    };
    auto sumb=[&](int l,int r){
      //1-indeded
      return suma(r)-suma(l-1)  ;
    };
    while(q--){
        int com,x,y;
        cin >> com >> x >> y;
        if(com==0){
            add(x-1,y);
        }else{
            cout << sumb(x,y) << "\n";
        }
    }
}
accuracy: 1
time_ms: 50
memory_kb: 3968
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

int N = 1;
int v[140000];

void add(int i, int x) {
    for(int t = i; t < N; t |= (t + 1)) v[t] += x;
}

int sum(int i) {
    int ans = 0;
    for(int t = i; t > 0; t &= (t - 1)) ans += v[t - 1];
    return ans;
}

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    
    int n, q;
    cin >> n >> q;
    while(N < n) N <<= 1;
    
    while(q--) {
        int cmd;
        cin >> cmd;
        
        if(cmd == 0) {
            int i, x;
            cin >> i >> x;
            --i;
            
            add(i, x);
        }
        
        if(cmd == 1) {
            int s, t;
            cin >> s >> t;
            --s;
            
            cout << sum(t) - sum(s) << endl;
        }
    }
    
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3812
final_rank: 5

code_snippet: #include<iostream>
#include<vector>
using namespace std;

template<typename T>
class BIT{
	int n;
	vector<T> node;
public:
	BIT(int N): n(N){ node = vector<T>(n + 1, 0);}
	
	void add(int x, T y){
		while(x <= n){
			node[x] += y;
			x += x & (-x);
		}
	}
	
	T sum(int i){
		T s = 0;
		while(i > 0){
			s += node[i];
			i -= i & (-i);
		}
		return s;
	}
	
	T solve(int l, int r){
		return sum(r) - sum(l - 1);
	}
};

int main(){
	int n, q;
	cin >> n >> q;
	BIT<int> bt(n);
	int com, x, y;
	while(q--){
		cin >> com >> x >> y;
		if(com) cout << bt.solve(x, y) << endl;
		else bt.add(x, y);
	}
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3712
final_rank: 4

code_snippet: #include<iostream>
#include<vector>
#include<functional>
using namespace std;

template<typename T>
class Seg_tree{
	int n;
	T st;
	vector<T> node;
	function<T(T, T)> func;
public:
	Seg_tree(int N, function<T(T, T)> f, T m = 0): func(f), st(m){
		n = 1;
		while(n < N) n *= 2;
		node = vector<T>(2 * n - 1, st);
	}
	
	void set(int x, T y){
		x += n - 1;
		node[x] += y;
		while(x > 0){
		    x = (x - 1) / 2;
			node[x] = func(node[2 * x + 1], node[2 * x + 2]);
		}
	}
	
	T solve(int l, int r){
		l += n - 1, r += n - 1;
		T vl = st, vr = st;
		while(l < r){
			if(l % 2 == 0) {vl = func(vl, node[l]), l++;}
			l /= 2;
			if(r % 2 == 0) {r--, vr = func(vr, node[r]);}
			r /= 2;
		}
		return func(vl, vr);
	}
	
	//void putv() { for(int i = n - 1; i < 2 * n - 1; i++) cout << node[i] << endl;}
};

int main(){
	int n, q;
	cin >> n >> q;
	Seg_tree<long long> st(n, [](long long a, long long b){ return a + b;});
	long long com, x, y;
	while(q--){
		cin >> com >> x >> y;
		if(com) cout << st.solve(x - 1, y) << endl;
		else st.set(x - 1, y);
	}
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 5456
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;

int main(){
    ll n,q; cin>>n>>q;
    vector<ll> A(n+1,0);

    for(int i=0;i<q;i++){
        int com; cin>>com;
        if(com==0){
            ll i,x; cin>>i>>x;
            while(i<=n){
                A[i]+=x;
                i+=i&-i;
            }
        }
        if(com==1){
            ll s,t; cin>>s>>t; s--;
            ll ssum=0,tsum=0;
            while(s>0){
                ssum+=A[s];
                s-=s&-s;
            }
            while(t>0){
                tsum+=A[t];
                t-=t&-t;
            }
            cout<<tsum-ssum<<endl;;
        }
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3860
final_rank: 8

code_snippet: #include <iostream>
#include <vector>

int n;

void add(int i, int x, std::vector<long long> &segTree) {
    i += n;  // 0-indexed to leaf
    segTree[i] += x;
    while (i > 1) { // update parents
        i /= 2;
        segTree[i] = segTree[2*i] + segTree[2*i + 1];
    }
}

long long getSum(int s, int t, std::vector<long long> &segTree) {
    long long res = 0;
    s += n;
    t += n;
    while (s <= t) {
        if (s % 2 == 1) res += segTree[s++];
        if (t % 2 == 0) res += segTree[t--];
        s /= 2;
        t /= 2;
    }
    return res;
}

int main() {
    int q;
    std::cin >> n >> q;

    std::vector<long long> segTree(2 * n, 0);

    for (int i = 0; i < q; ++i) {
        int com, x, y;
        std::cin >> com >> x >> y;
        if (com == 0) add(x, y, segTree);         // 0-indexed
        else std::cout << getSum(x, y, segTree) << '\n';
    }
}
accuracy: 1
time_ms: 80
memory_kb: 4556
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, e) for (int i = (int)(s); i < (int)(e); ++i)

template<typename T>
struct FenwickTree {
	vector<T> data;
	FenwickTree(int size) : data(size + 1, 0) {}
	
	void add(int k, T x) {
		for (++k; k < data.size(); k += k & -k) data[k] += x;
	}
	
	T sum(int k) { // [0, a]
		if (k < 0) return 0;
		T res = 0;
		for (++k; k > 0; k -= k & -k) res += data[k];
		return res;
	}
	
	T sum(int l, int r) { // [l, r]
		return sum(r) - sum(l - 1);
	}
};

int main() {
	cin.tie(nullptr);
	ios_base::sync_with_stdio(false);
	
	int N, Q;
	cin >> N >> Q;
	
	FenwickTree<ll> BIT(N);
	
	rep(query, 0, Q) {
		int t, x, y;
		cin >> t >> x >> y;
		
		if (t == 0) {
			--x;
			BIT.add(x, y);
		} else {
			--x, --y;
			cout << BIT.sum(x, y) << '\n';
		}
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3856
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
using Graph = vector<vector<int>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(int i = a; i < b; i++)
#define all(v) v.begin(), v.end()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define inf 1070000000
#define INF 4500000000000000000
#define MOD 998244353
//#define MOD 1000000007
#define pi 3.14159265358979

template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

//xのn乗
ll llpow(ll x, ll n) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
ll modpow(ll x, ll n, ll mod) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans = ans * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ans;
}
//mod pでのaの逆元
ll inverse(ll a, ll p) {
    return modpow(a, p-2, p);
}
//nの階乗
ll fact(ll n) {
    if(n == 0) return 1;
    else return n * fact(n-1);
}
ll modfact(ll n, ll mod) {
    if(n == 0) return 1;
    else return (n * modfact(n-1, mod)) % mod;
}
//nCr=n!/r!(n-r)! mod p
ll comb(ll n, ll r, ll mod) {
    ll a = modfact(n, mod), b = modfact(r, mod), c = modfact(n-r, mod);
    b = inverse(b, mod); c = inverse(c, mod);
    return (((a*b)%mod)*c)%mod;
}

//1+2+...+n = n(n+1)/2
ll triangle(ll n) {
    ll x = n*(n+1);
    return x/2;
}
//素数判定
bool is_prime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
//左回転
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
double dist(ll a, ll b, ll x, ll y) {
    return sqrt((a-x)*(a-x) + (b-y)*(b-y));
}
int man(int a, int b, int x, int y) {
    return abs(a-x) + abs(b-y);
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}

//hh:mm:ss to second
int convert_to_time(string S) {
    ll h = 10*(S[0]-'0') + (S[1]-'0');
    ll m = 10*(S[3]-'0') + (S[4]-'0');
    ll s = 10*(S[6]-'0') + (S[7]-'0');
    
    return h*3600+m*60+s;
}

//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    rep(i,0,H) rep(j,0,W) dist[i][j] = inf;
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
void floyd(vector<vector<ll>> &G) {
    int N = G.size();
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(G[i][j] > G[i][k] + G[k][j]) {
                    G[i][j] = G[i][k] + G[k][j];
                }
            }
        }
    }
}

//Union-Find
vector<int> par(0);
int root(int x) {
    if(par[x] == x) {
        return x;
    }else {
        return par[x] = root(par[x]);
    }
}
bool same(int x, int y) {
    return root(x) == root(y);
}
void unite(int x, int y) {
    x = root(x);
    y = root(y);
    if(x == y) return;
    par[x] = y;
}

void solve() {
}

int main() {
    int N, Q, tmp = 1; cin >> N >> Q;
    while(tmp < N) tmp *= 2;
    vector<ll> A(2*tmp, 0);

    while(Q--) {
        int com; cin >> com;
        if(com == 0) {
            int i; ll x; cin >> i >> x; i--;
            int p = tmp + i;
            A[p] += x;
            while(p != 1) {
                A[p/2] += x;
                p /= 2;
            }
        }
        if(com == 1) {
            int s, t; cin >> s >> t; s--, t--;
            int p = tmp + s, q = tmp + t;

            if(p == q) {
                cout << A[p] << "\n";
                continue;
            }

            ll ans = 0;
            while(p/2 != q/2) {
                if(p % 2 == 1) ans -= A[p-1];
                p /= 2;

                if(q % 2 == 0) ans -= A[q+1];
                q /= 2;
            }

            cout << A[p/2] + ans << "\n";
        }
    }

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 5096
final_rank: 18

code_snippet: #define _GLGBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

int n, q, tree_length = 1;
vector<int> segment_tree;

int segment_tree_build(int node) {
    int left = 2 * node, right = 2 * node + 1;

    if (left < tree_length) {
        return segment_tree.at(node) = segment_tree_build(left) + segment_tree_build(right);
    } else
        return segment_tree.at(node);
}

void segment_tree_add(int x, int y) {
    x = tree_length / 2 + x;

    segment_tree.at(x) += y;

    while (true) {
        x /= 2;

        if (x)
            segment_tree.at(x) = segment_tree.at(x * 2) + segment_tree.at(x * 2 + 1);
        else
            break;
    }
}

int segment_tree_get_sum(int x, int y, int l = 1, int r = tree_length / 2, int pos = 1) {
    int res = 0;

    if (y <= l || r <= x)
        return 0;
    
    if (x <= l && r <= y) {
        return segment_tree[pos];
    }

    return res += segment_tree_get_sum(x, y, l, (l + r) / 2, pos * 2) + segment_tree_get_sum(x, y, (l + r) / 2, r, pos * 2 + 1);
}

int main()
{
    cin >> n >> q;

    if (n == 1)
        segment_tree.push_back(0);
    else {
        while(2 * n > tree_length)
            tree_length *= 2;

        segment_tree.resize(tree_length);

        for (int i = tree_length / 2; i < tree_length; i++)
            segment_tree.at(i) = 0;

        segment_tree_build(1);
    }

    for (int j = 0; j < q; j++) {
        int com, x, y;
        cin >> com >> x >> y;

        if (com == 0) {
            if (n == 1)
                segment_tree.at(--x) += y;
            else
                segment_tree_add(--x, y);
        } else {
            if (n == 1)
                cout << segment_tree.at(--x) << '\n';
            else
                cout << segment_tree_get_sum(--x, y, 0, tree_length / 2, 1) << '\n';
        }
    }

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 4120
final_rank: 15

code_snippet: #define _GLGBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

int n, q, tree_length = 1;
vector<int> segment_tree;

int segment_tree_build(int node) {
    int left = 2 * node, right = 2 * node + 1;

    if (left < tree_length) {
        return segment_tree.at(node) = segment_tree_build(left) + segment_tree_build(right);
    } else
        return segment_tree.at(node);
}

void segment_tree_add(int x, int y) {
    x = tree_length / 2 + x;

    segment_tree.at(x) += y;

    while (true) {
        x /= 2;

        if (x)
            segment_tree.at(x) = segment_tree.at(x * 2) + segment_tree.at(x * 2 + 1);
        else
            break;
    }
}

int segment_tree_getSum(int x, int y) {
    int res = 0;

    x = tree_length / 2 + x;
    y = tree_length / 2 + y;

    while (x < y) {
        if (x % 2)
            res += segment_tree.at(x++);

        x /= 2;

        if (y % 2) 
            res += segment_tree.at(--y);
        
        y /= 2;
    }

    return res;
}

int main()
{
    cin >> n >> q;

    if (n == 1)
        segment_tree.push_back(0);
    else {
        while(2 * n > tree_length)
            tree_length *= 2;

        segment_tree.resize(tree_length);

        for (int i = tree_length / 2; i < tree_length; i++)
            segment_tree.at(i) = 0;

        segment_tree_build(1);
    }

    for (int j = 0; j < q; j++) {
        int com, x, y;
        cin >> com >> x >> y;

        if (com == 0) {
            if (n == 1)
                segment_tree.at(--x) += y;
            else
                segment_tree_add(--x, y);
        } else {
            if (n == 1)
                cout << segment_tree.at(--x) << '\n';
            else
                cout << segment_tree_getSum(--x, y) << '\n';
        }
    }

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4144
final_rank: 11