#include <cstdio>
#define left(i) ((i)<<1)
#define right(i) (((i)<<1)|1)
#define mijloc(i, j) (((i)+(j))>>1)
#define maxn 1<<15
//VECTORUL S trebuie sa aiba un numar MAI MARE decat 2*n dar sa fie de forma 2^k (arborele trebuie sa fie complet)
// cu ajutorul arborilor de intervale se pot rezolva mai multe tipuri de probleme decat se poate rezolva cu arborii indexati binar
// de ce am folosit "define-urile" in loc sa folosesc functii? (ex: int left(int i) { return (i<<1);})
// pt k in momentul compilarii, c-ul sterge unde gaseste "left(i)" si scrie i<<1 , pe scurt nu se apeleaza nici o functie
// e ca si cum am scrie direct
// mijloc(i, j) = (i+j)/2
// left(i) = 2*i
// right(i) = 2*i+1
// operatiile pe biti sunt de vreo 10 ori mai rapide decat inmultirile sau impartirile si de vreo 2 ori mai rapide decat adunarile si scaderile ;))
// 1<<15 = 2^15= (aproximativ)32000
int s[maxn], n, m;
//sgn = semn ( se aduna sau se scada)
//daca nu puneam sgn trebuia sa fi scris de 2 ori functia...odata pt initializare si odata pt operatii
inline void update(int n, int l, int r, int p, int v, int sgn)
{
int m=mijloc(l,r);
s[n]+=v*sgn;
if(l==r) return;
if(p<=m) update(left(n), l, m, p, v, sgn);
else update(right(n), m+1, r, p, v, sgn);
}
inline int query(int n, int l, int r, int a, int b)
{
int t=0;
if(a<=l && r<=b)return s[n];
int m=mijloc(l, r);
if(a<=m) t+=query(left(n), l, m, a, b);
if(b>m) t+=query(right(n), m+1, r, a, b);
return t;
}
int main()
{
int i;
freopen("datorii.in", "r", stdin);
freopen("datorii.out", "w", stdout);
scanf("%d %d\n", &n, &m);
for(i=1;i<=n;i++){ int p; scanf("%d ", &p); update(1, 1, n,i, p, 1);}
for(i=1;i<=m;i++)
{
int p, q, t;
scanf("%d %d %d\n", &p, &q, &t);
if(p==0) update(1, 1, n, q, t, -1);
else printf("%d\n", query(1, 1, n, q, t));
}
return 0;
}