#include <cstdio>
#include <algorithm>
#define Infinity 2000000000
#define NMax 500000
using namespace std;
struct TreeNode
{
int Upd, Max, Sum;
};
TreeNode Tree[NMax];
inline void Update (int, int, int, int);
inline void PushDown (int, int, int);
inline void PushDown (int Node, int Left, int Right)
{
int Middle=(Left+Right)/2;
if (Tree[Node].Upd==0)
{
return; //nu am ce informatie sa imping in jos
}
Update (2*Node, Left, Middle, Tree[Node].Upd); //imping informatia in fiul stang
Update (2*Node+1, Middle+1, Right, Tree[Node].Upd); //imping informatia in fiul drept
Tree[Node].Upd=0; //sterg informatia din nodul curent
}
inline void Update (int Node, int Left, int Right, int UpdateLeft, int UpdateRight, int Val)
{
int Middle=(Left+Right)/2;
if (UpdateLeft<=Left and Right<=UpdateRight)
{
Tree[Node].Upd+=Val; //cresc valoarea adaugata la elementele din intervalul curent
Tree[Node].Max+=Val; //cresc si valoarea minimului din intervalul curent
Tree[Node].Sum+=(Val*(Right-Left+1)); //actualizez suma pe intervalul curent
return;
}
PushDown (Node, Left, Right); //imping informatia din nodul curent in jos ca sa nu ma incurce
if (UpdateLeft<=Middle)
{
Update (2*Node, Left, Middle, UpdateLeft, UpdateRight, Val); //actualizez fiul stang
}
if (UpdateRight>Middle)
{
Update (2*Node+1, Middle+1, Right, UpdateLeft, UpdateRight, Val); //actualizez fiul drept
}
Tree[Node].Sum=Tree[2*Node].Sum+Tree[2*Node+1].Sum;
Tree[Node].Max=max (Tree[Node].Max, Tree[Node].Max);
}
inline int QuerySum (int Node, int Left, int Right, int QueryLeft, int QueryRight)
{
int Middle=(Left+Right)/2;
if (QueryLeft<=Left and Right<=QueryRight)
{
return Tree[Node].Sum; //intervalul curent e cuprins in totalitate in intervalul pe care fac query
}
PushDown (Node, Left, Right); //imping informatia din nodul curent in jos ca sa nu ma incurce
int NodeSum=0;
if (QueryLeft<=Middle)
{
NodeSum+=QuerySum (2*Node, Left, Middle, QueryLeft, QueryRight);
}
if (QueryRight>Middle)
{
NodeSum+=QuerySum (2*Node+1, Middle+1, Right, QueryLeft, QueryRight);
}
return NodeSum;
}
inline int QueryMax (int Node, int Left, int Right, int QueryLeft, int QueryRight)
{
int Middle=(Left+Right)/2;
if (QueryLeft<=Left and Right<=QueryRight)
{
return Tree[Node].Max; //intervalul curent e cuprins in totalitate in intervalul pe care fac query
}
PushDown (Node, Left, Right); //imping informatia din nodul curent in jos ca sa nu ma incurce
int NodeMax=-Infinity;
if (QueryLeft<=Middle)
{
NodeMax=max (NodeMax, QueryMax (2*Node, Left, Middle, QueryLeft, QueryRight));
}
if (QueryRight>Middle)
{
NodeMax=max (NodeMax, QueryMax (2*Node+1, Middle+1, Right, QueryLeft, QueryRight));
}
return NodeMax;
}
int main ()
{
freopen ("datorii.in", "r", stdin);
freopen ("datorii.out", "w", stdout);
int NQ; scanf ("%d %d", &N, &NQ);
for (int i=1; i<=N; ++i)
{
scanf ("%d", &X);
Update (1, 1, N, i, i, X);
}
for (; NQ>0; --NQ)
{
int Type, X, Y; scanf ("%d %d %d", &Type, &X, &Y);
if (Type==0)
{
Update (1, 1, N, X, X, -Y);
}
else
{
printf ("%d\n", QuerySum (1, 1, N, X, Y));
}
}
return 0;
}