/**
* Tushar Roy --> https://www.youtube.com/watch?v=CWDQJGaN1gY&t=10s
* GeeksForGeeks --> https://www.youtube.com/watch?v=4SNzC4uNmTA&t=165s
*/
#include <fstream>
#define N_MAX 100000
int N, M;
FILE *fin, *fout;
void swap(int &a, int &b){
int temp = a;
a = b; b = temp;
}
class BinaryIndexTree{
private:
int bit_prefix_sum[N_MAX+1];
int bit_index_keeper[N_MAX+1];
int getNextNode(int previous) {
return previous + (previous & -previous);
}
int getParent(int child) {
return child - (child & -child);
}
void qSortIndexes(int left, int right){
int i = left, j = right;
int middle = (left + right) / 2;
while(i < j) {
while (bit_prefix_sum[bit_index_keeper[i]] < bit_prefix_sum[bit_index_keeper[middle]])
i++;
while (bit_prefix_sum[bit_index_keeper[j]] > bit_prefix_sum[bit_index_keeper[middle]])
j--;
if (i <= j) {
swap(bit_index_keeper[i],bit_index_keeper[j]);
i++; j--;
}
//if equal, sort by index, which means cancelling the previous `swap()`
if(bit_prefix_sum[bit_index_keeper[i]] == bit_prefix_sum[bit_index_keeper[j]]){
if(bit_index_keeper[i] > bit_index_keeper[j])
swap(bit_index_keeper[i],bit_index_keeper[j]);
}
}
if(j > left) qSortIndexes(left,j);
if(i < right) qSortIndexes(i, right);
}
int bSearch(int sum_to_find, int left, int right){
int middle = 0;
while(left < right){
middle = (left + right) / 2;
if(sum_to_find <= bit_prefix_sum[bit_index_keeper[middle]]){
right = middle;
}
else
if(sum_to_find > bit_prefix_sum[bit_index_keeper[middle]]){
left = middle + 1;
}
}
if(left == right && sum_to_find == bit_prefix_sum[bit_index_keeper[left]])
return bit_index_keeper[left];
else
return -1;
/*if(bit_prefix_sum[bit_index_keeper[middle]] == sum_to_find){
return bit_index_keeper[middle];
} else
if(bit_prefix_sum[bit_index_keeper[middle]] >= sum_to_find && left < middle)
bSearch(sum_to_find, left, middle);
else
if(bit_prefix_sum[bit_index_keeper[middle]] < sum_to_find && right > middle)
bSearch(sum_to_find, middle+1, right);
else return -1;*/
}
public:
void update(int i, int val_to_add) {
while(i <= N){
bit_prefix_sum[i] += val_to_add;
i = getNextNode(i);
}
}
int getSumUpTo(int i) {
int sum = 0;
while(i > 0){
sum = sum + bit_prefix_sum[i];
i = getParent(i);
}
return sum;
}
void setIndex(int index){
bit_index_keeper[index] = index;
}
//quick sort + binary search O(log^2(n))
int getMinIndexOfSum(int sum_to_find){
qSortIndexes(1,N);
return bSearch(sum_to_find, 1, N);
}
} BITree;
void constructBITree(){
fscanf(fin, "%d%d", &N, &M);
for(int i = 1, new_value; i <= N; i++){
fscanf(fin, "%d", &new_value);
BITree.update(i, new_value);
BITree.setIndex(i);
}
}
void solve(){
int operation, a, b, sum;
for(int i = 1; i <= M; i++){
fscanf(fin, "%d", &operation);
switch(operation){
case 0:
fscanf(fin, "%d%d", &a, &b);
BITree.update(a, b);
break;
case 1:
fscanf(fin, "%d%d", &a, &b);
fprintf(fout, "%d\n", BITree.getSumUpTo(b) - BITree.getSumUpTo(a-1));
break;
case 2:
fscanf(fin, "%d", &sum);
fprintf(fout, "%d\n", BITree.getMinIndexOfSum(sum));
break;
default:
fprintf(fout, "Invalid operation!\n");
}
}
}
int main(){
fin = fopen("aib.in", "r");
fout = fopen("aib.out", "w");
constructBITree();
solve();
fclose(fin);
fclose(fout);
return 0;
}