#include <iostream>
#include <fstream>
using namespace std;
#define MAXN 100001
#define IPair pair<int,int>
int N, M;
IPair tree[4 * MAXN + 100];
int updateValue;
int updatePlace;
void build(int, int, int);
void update(int, int, int);
int sumStart, sumEnd;
int sum;
void sumCalc(int, int, int);
int sumToFind, rollingSum;
int k;
void sumFind(int, int, int);
int height = 0;
int capacity = 1;
int main()
{
ifstream f("aib.in");
ofstream g("aib.out");
// Program
f >> N >> M;
int cN = N;
bool up = false;
if (cN % 2 == 1) up = true;
while (cN >>= 1)
{
if (cN != 1 && cN % 2 == 1) up = true;
++height;
}
if (up) ++height;
while (height)
{
capacity *= 2;
height--;
}
for (int i = 1; i <= N; i++)
{
f >> updateValue;
updatePlace = i;
build(1, 1, N);
}
for (int i = 0; i < M; i++)
{
int c, a, b;
f >> c;
if (c == 0)
{
f >> a >> b;
updatePlace = a;
updateValue = b;
update(1, 1, N);
}
else if (c == 1)
{
f >> a >> b;
sumStart = a;
sumEnd = b;
sum = 0;
sumCalc(1, 1, N);
g << sum << '\n';
}
else
{
f >> a;
sumToFind = a;
rollingSum = 0;
k = 0;
sumFind(1, 1, N);
g << k <<'\n';
}
}
// Exit
f.close();
g.close();
return 0;
}
IPair add(IPair a, IPair b)
{
return make_pair(a.first + b.first, a.second + b.second);
}
void build(int treePlace, int treeStart, int treeEnd)
{
if (treeStart == treeEnd)
{
tree[treePlace] = make_pair(updateValue,1);
return;
}
int mij = (treeStart + treeEnd) / 2;
if (updatePlace <= mij) build(2 * treePlace, treeStart, mij);
else build(2 * treePlace + 1, mij + 1, treeEnd);
tree[treePlace] = add(tree[2 * treePlace], tree[2 * treePlace + 1]);
}
void update(int treePlace, int treeStart, int treeEnd)
{
if (treeStart == treeEnd)
{
tree[treePlace].first += updateValue;
return;
}
int mij = (treeStart + treeEnd) / 2;
if (updatePlace <= mij) update(2 * treePlace, treeStart, mij);
else update(2 * treePlace + 1, mij + 1, treeEnd);
tree[treePlace].first = tree[2 * treePlace].first + tree[2 * treePlace + 1].first;
}
void sumCalc(int treePlace, int treeStart, int treeEnd)
{
if (sumStart <= treeStart && treeEnd <= sumEnd)
{
sum += tree[treePlace].first;
return;
}
int mij = (treeStart + treeEnd) / 2;
if (sumStart <= mij) sumCalc(2 * treePlace, treeStart, mij);
if (mij + 1 <= sumEnd) sumCalc(2 * treePlace + 1, mij + 1, treeEnd);
}
void sumFind(int treePlace, int treeStart, int treeEnd)
{
if (rollingSum + tree[treePlace].first == sumToFind)
{
k += tree[treePlace].second;
return;
}
if (tree[treePlace].first >= (sumToFind-rollingSum))
{
try
{
if (tree[2*treePlace].first == 0)
{
k = -1;
return;
}
}
catch (const std::exception&)
{
k = -1;
return;
}
sumFind(2 * treePlace, treeStart, treeEnd);
}
else //if (tree[treePlace] < sumToFind)
{
// *
// / \
// h e
if (treePlace == 0)
{
k = -1;
return; // we have the highset sum, nothing to do
}
if (tree[treePlace].second == 1 && treePlace % 2 == 1)
{
k = -1;
return; // we are a leaf and on the right and we want to go right... no can do
}
k += tree[treePlace].second;
rollingSum += tree[treePlace].first;
sumFind(treePlace + 1, treeStart, treeEnd);
}
}