#include<stdio.h>
#include<math.h>
#define NMAX 100001
int N, M, A[NMAX], S[NMAX];
//S este sirul prin care se reprezinta arborele binar
int binary_zeros(int x){
//determina numarul zerourilor finale ale reprezentarii in binar a unui numar
int r, no = 0;
do{
r = x % 2;
if(r == 0)
no++;
x = x/2;
}while(r == 0 && x != 0);
return no;
}
void modify(int pos, int val){
//adauga val elementului de pe pozitia pos. Este folosita pt op de tip 0
int k;
while(pos <= N){
S[pos] = S[pos] + val;
k = binary_zeros(pos);
pos = pos + pow(2, k);
}
}
int sum(int pos){
//calculeaza suma de la 1 la pos
int res = 0, k;
while(pos > 0){
res = res + S[pos];
k = binary_zeros(pos);
pos = pos - pow(2, k);
}
return res;
}
int query_sum(int left, int right){
//returneaza suma elem din intervalul [left, right] pt operatia de tip 1
int sum1, sum2, res;
sum1 = sum(left - 1);
sum2 = sum(right);
res = sum2 - sum1;
return res;
}
int pos_sum(int val){
//returneaza pozitia minima pe care suma elem este egala cu val pt operatia de tip 2
int i = 1, res;
do{
res = sum(i);
if(res == val)
return i;
i++;
}while(i <= N);
return -1;
}
void read_solve_print(FILE *pf, FILE *pg){
int i, j, code, a, b, sum, k, pos;
fscanf(pf, "%d %d", &N, &M);
for(i = 1; i <= N; i++){
fscanf(pf, "%d", &A[i]);
k = binary_zeros(i);
sum = 0;
for(j = i - pow(2, k) + 1; j <= i; j++)
sum = sum + A[j];
S[i] = sum;
}
for(i = 1; i <= M; i++){
fscanf(pf, "%d", &code);
if(code == 0){
fscanf(pf, "%d %d", &a, &b);
modify(a, b);
}
else
if(code == 1){
fscanf(pf, "%d %d", &a, &b);
sum = query_sum(a, b);
fprintf(pg, "%d\n", sum);
}
else{
fscanf(pf, "%d", &a);
pos = pos_sum(a);
fprintf(pg, "%d\n", pos);
}
}
}
int main(){
FILE *pf, *pg;
pf = fopen("aib.in", "r");
pg = fopen("aib.out", "w");
read_solve_print(pf, pg);
fclose(pf);
fclose(pg);
return 0;
}