import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
bool DEBUG = 0; void log(A ...)(lazy A a){ if(DEBUG) print(a); }
void main(string[] args){ args ~= ["", ""]; string cmd = args[1]; if(cmd == "-debug") DEBUG = 1;
if(cmd == "-gen") gen; else if(cmd == "-jury") jury; else solve; } 
void print(){ writeln(""); } void print(T)(T t){ writeln(t); } void print(T, A ...)(T t, A a){ std.stdio.write(t, " "), print(a); }
string unsplit(T)(T xs){ return xs.array.to!(string[]).join(" "); }
string scan(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T scan(T)(){ return scan.to!T; } T[] scan(T)(int n){ return n.iota.map!(i => scan!T()).array; }
T lowerTo(T)(ref T x, T y){ if(x > y) x = y; return x; } T raiseTo(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //
void gen(){}
void jury(){}
void solve(){

  int n = scan!int, q = scan!int;
  long[] as = scan!long(n);
  log("as:", as);
  
  auto seg = new SegTree!long(0, n, (a, b) => a + b, 0);
  foreach(int i, a; as) seg.setValue(i, a);
  log("seg:", seg);
  
  foreach(_; 0 .. q){
  
    int c = scan!int;
    if(c == 0){
      int p = scan!int;
      long x = scan!long;
      seg.setValue(p, seg.getValue(p, p + 1) + x);
	  log("p:", p, "x:", x, "seg:", seg);
    }
    else{
      int l = scan!int, r = scan!int;
      seg.getValue(l, r).print;
    }

  }
  
}

/*
セグメント木 区分木 segtree segment tree
1点に書き込み、範囲で読み出す。
たとえば [l, r) の最大値を求めるなど。
引数
a, b　添字の範囲。 この意味はa から b - 1 までなので注意。
marge　左の子と右の子から自分の値をきめる関数（たとえばmax）
neutral　すべての x に対して marge(x, z) = x をみたすz（たとえば-infty）
*/
class SegTree(T){
	T value;
	T neutral;
	SegTree left, right; // 左の子(a <= x < c)、右の子(c <= x < b)
	bool hasValue;
	bool isTerminal;
	int a, b; // a <= x < b を担当する
	T delegate(T, T) marge;
	this(int a, int b, T delegate(T, T) marge, T neutral = T.init){
		this.a = a, this.b = b;
		this.marge = marge;
		this.neutral = neutral;
		if(b - a == 1){
			this.isTerminal = 1;
		}
		else{
			int c = (a + b) / 2;
			this.left = new SegTree(a, c, marge, neutral);
			this.right = new SegTree(c, b, marge, neutral);
		}
	}
	
	// [a, b) における値を読む ※[a, b) はこのノードの担当区間とかぶっていなくてもよい
	T getValue(int a, int b){
		if(b <= this.a || this.b <= a) return neutral;
		if(a <= this.a && this.b <= b){
			if(! this.hasValue){
				T v1 = this.left.getValue(a, b), v2 = this.right.getValue(a, b);
				T v = marge(v1, v2);
				this.value = v;
				this.hasValue = 1;
			}
			return this.value;
		}
		else{
			T v1 = this.left.getValue(a, b), v2 = this.right.getValue(a, b);
			T v = marge(v1, v2);
			return v;
		}
	}
	
	
	// i における値を設定
	void setValue(int i, T value){
		assert(a <= i && i < b);
		this.hasValue = 0; // これが漏れていた！！
		if(this.isTerminal){
			this.hasValue = 1;
			this.value = value;
		}
		else if(i < left.b) left.setValue(i, value);
		else right.setValue(i, value);
	}
	
	// 配列に変換したもの（デバッグ用）
	T[] array(){
		if(this.isTerminal) return [this.value];
		else return this.left.array ~ this.right.array;
	}
	
	// 文字列に変換したもの（デバッグ用）
	override string toString(){
		return this.array.to!string;
	}
}
