#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#define all(x) (x).begin(),(x).end()
#pragma GCC optimize ("-O3")
using namespace std; void _main(); int main() { cin.tie(0); ios::sync_with_stdio(false); _main(); }
typedef long long ll; const int inf = INT_MAX / 2; const ll infl = 1LL << 60;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a = b; return 1; } return 0; }
//---------------------------------------------------------------------------------------------------
template<class T, T def> struct SuperSegTree {
    struct dice {mt19937 mt; dice() { random_device rd; mt = mt19937(rd()); }
        int operator()(int x) { return this->operator()(0, x - 1); }
        int operator()(int x,int y){uniform_int_distribution<int> dist(x,y);return dist(mt); }} dc;
    struct Node {
        int val;Node *lch, *rch;int sz;T data,ans;Node(int a,T d):val(a),lch(0),rch(0),sz(1){init(d);}
        void init(T d) { data = d; ans = data; }void push() { }
        void update(){ans=data;if(lch) ans=comp(ans, lch->ans);if (rch) ans = comp(ans, rch->ans);}

        // Modify!! -----------------------------
        T comp(T a, T b) { return a + b; }
        // --------------------------------------
    };

    SuperSegTree() { root = new Node(inf, def); }
    Node *root;
    inline int getsz(Node *t) { return t ? t->sz : 0; }
    int getsz() { return getsz(root); }
    inline void push(Node *t) {if (t == NULL)return;t->push();}
    inline Node *update(Node *t) {if (!t)return NULL;t->sz = getsz(t->lch) + getsz(t->rch) + 1;
        t->update();return t;}
    Node *merge(Node *a, Node *b) {push(a); push(b);if (!a)return b;if (!b)return a;
        if (dc(getsz(a) + getsz(b))<getsz(a)) {a->rch = merge(a->rch, b);return update(a);}
        else {b->lch = merge(a, b->lch);return update(b);}}
    template<class... V> Node *merge(Node *a, V... y) { return merge(a, merge(y...)); }
    pair<Node *, Node *>split(Node *t, int k) { // [0,k) [k,N)
        push(t);if (!t)return make_pair(t, t);if (k <= getsz(t->lch)) {
        pair<Node *, Node *>s = split(t->lch, k);t->lch = s.second;
        return make_pair(s.first, update(t));}
        else {pair<Node *, Node *>s = split(t->rch, k - getsz(t->lch) - 1);t->rch = s.first;
        return make_pair(update(t), s.second);}}
    int lower_bound(int x) { return lower_bound(root, x); }
    int lower_bound(Node *t,int x){push(t);if(!t)return 0;if(t->val>=x)return lower_bound(t->lch,x);
        return lower_bound(t->rch, x) + getsz(t->lch) + 1;}
    tuple<Node*, Node*, Node*> split3(int l, int r) { // [0,l) [l,r] (r,N)
        auto p = split(root, l); auto a = p.first; auto q = split(p.second, r - l + 1);
        auto b = q.first;auto c = q.second;root = 0;return make_tuple(a, b, c);}
    void dump() { dump(root); cout << endl; }
    void dump(Node *t) {if (t == NULL)return;push(t);dump(t->lch);
        cout << t->val <<" : " << t->data << endl;dump(t->rch);}
    T get(int i) {return get(i, i);}
    void update(int i, T v) {int k = lower_bound(i);Node *a, *b, *c;tie(a, b, c) = split3(k, k);
        if (b != NULL && b->val == i) b = new Node(i, v);else b = merge(new Node(i, v), b);
        root = merge(a, b, c);}
    T get(int l, int r) { // [l,r]
        int kl = lower_bound(l);int kr = lower_bound(r);Node *a, *b, *c;tie(a, b, c) = split3(kl, kr);
        T res = def;if (kl == kr) {if (b) if(l <= b->val && b->val <= r) res = b->ans;} else {
        if (b) res = b->ans;}root = merge(a, b, c);return res;}
    void add(int i, T v) {update(i, get(i) + v);}
};
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧  
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i     
　　　　／　　　＼　 　  |　|     
　　　 /　　 /￣￣￣￣/　　|  
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿  
　 　　　＼/＿＿＿＿/　（u　⊃  
---------------------------------------------------------------------------------------------------*/








/*

答えは4種類しか無い

0: 同じ範囲を指す
1: 範囲が被っていない
-1: 範囲が被っていて、どちらとも範囲が被っていない範囲が存在しない
2: 範囲が被っていて、どちらとも範囲が被っていない範囲が存在する

*/








/*
int N, M, A[101010], B[101010];
void _main() {
    cin >> N;
    rep(i, 0, N) cin >> A[i];
    rep(i, 0, N) {
        B[i] = 1;
        rep(i, 0, A[i]) B[i] *= 2;
    }
    rep(i, 1, N) B[i] += B[i - 1];

    cin >> M;
    vector<pair<int, int>> ans;
    rep(i, 0, M) {
        int L, R; cin >> L >> R;
        L--; R--;
        
        int sm = B[R];
        if (L) sm -= B[L - 1];

        ans.push_back({ sm, i + 1 });
    }
    sort(all(ans));
    rep(i, 0, M) {
        if (i) printf(" ");
        printf("%d", ans[i].second);
    }
    printf("\n");
}




*/



template <class Monoid>
struct dynamic_segment_tree { // on monoid
    typedef Monoid monoid_type;
    typedef typename Monoid::type underlying_type;
    struct node_t {
        int left, right; // indices on pool
        underlying_type value;
    };
    deque<node_t> pool;
    int root; // index
    int width; // of the tree
    int size; // the number of leaves
    Monoid mon;
    dynamic_segment_tree(Monoid const & a_mon = Monoid()) : mon(a_mon) {
        node_t node = { -1, -1, mon.unit() };
        pool.push_back(node);
        root = 0;
        width = 1;
        size = 1;
    }
protected:
    int create_node(int parent, bool is_right) {
        // make a new node
        int i = pool.size();
        node_t node = { -1, -1, mon.unit() };
        pool.push_back(node);
        // link from the parent
        assert(parent != -1);
        int & ptr = is_right ? pool[parent].right : pool[parent].left;
        assert(ptr == -1);
        ptr = i;
        return i;
    }
    int get_value(int i) {
        return i == -1 ? mon.unit() : pool[i].value;
    }
public:
    void point_set(int i, underlying_type z) {
        assert(0 <= i);
        while (width <= i) {
            node_t node = { root, -1, pool[root].value };
            root = pool.size();
            pool.push_back(node);
            width *= 2;
        }
        point_set(root, -1, false, 0, width, i, z);
    }
    void point_set(int i, int parent, bool is_right, int il, int ir, int j, underlying_type z) {
        if (il == j and ir == j + 1) { // 0-based
            if (i == -1) {
                i = create_node(parent, is_right);
                size += 1;
            }
            pool[i].value = z;
        }
        else if (ir <= j or j + 1 <= il) {
            // nop
        }
        else {
            if (i == -1) i = create_node(parent, is_right);
            point_set(pool[i].left, i, false, il, (il + ir) / 2, j, z);
            point_set(pool[i].right, i, true, (il + ir) / 2, ir, j, z);
            pool[i].value = mon.append(get_value(pool[i].left), get_value(pool[i].right));
        }
    }
    underlying_type range_concat(int l, int r) {
        assert(0 <= l and l <= r);
        if (width <= l) return mon.unit();
        return range_concat(root, 0, width, l, min(width, r));
    }
    underlying_type range_concat(int i, int il, int ir, int l, int r) {
        if (i == -1) return mon.unit();
        if (l <= il and ir <= r) { // 0-based
            return pool[i].value;
        }
        else if (ir <= l or r <= il) {
            return mon.unit();
        }
        else {
            return mon.append(
                range_concat(pool[i].left, il, (il + ir) / 2, l, r),
                range_concat(pool[i].right, (il + ir) / 2, ir, l, r));
        }
    }
};

struct plus_t {
    typedef int type;
    int unit() const { return 0; }
    int append(int a, int b) const { return a + b; }
};

dynamic_segment_tree<plus_t> bit;

SuperSegTree<int, 0> st1, st2;
void _main() {
    int n, q; cin >> n >> q;
    rep(_, 0, q) {
        int t; cin >> t;
        if (t == 0) {
            int x, y; cin >> x >> y;
            bit.point_set(x, bit.range_concat(x, x + 1) + y);
        }
        else {
            int x, y; cin >> x >> y;
            y++;
            int ans = bit.range_concat(x, y);
            printf("%d\n", ans);
        }
    }
}








int Q;

//---------------------------------------------------------------------------------------------------
void _main2() {
    cin >> Q;
    rep(q, 0, Q) {
        int t; cin >> t;
        if (t == 1) {
            int l, r;
            cin >> l >> r;
            st1.add(l, 1);
            st2.add(r, 1);
        }
        else if (t == 2) {
            int l, r;
            cin >> l >> r;
            st1.add(l, -1);
            st2.add(r, -1);
        }
        else {
            int a, b, c, d;
            cin >> a >> b >> c >> d;
            
            // =0
            if (a == c or b == d) {
                printf("0\n");
                continue;
            }

            // =1
            if (b < c or d < a) {
                printf("1\n");
                continue;
            }

            // =2
            int l = min(a, c);
            int r = max(b, d);

            if (0 < st2.get(1, l) or 0 < st1.get(r + 1, inf)) {
                printf("2\n");
                continue;
            }

            // =-1
            if (0 == st2.get(1, a) and 0 == st1.get(b + 1, inf)) {
                printf("-1\n");
                continue;
            }
            if (0 == st2.get(1, c) and 0 == st1.get(d + 1, inf)) {
                printf("-1\n");
                continue;
            }

            // =3
            printf("3\n");
        }
    }
}



Measured memory_bytes: 4648