/**
* Author: Sergey Kopeliovich (Burunduk30@gmail.com)
*/
#include <cstdio>
#include <cassert>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef _WIN32
# define I64 "%I64d"
#else
# define I64 "%Ld"
#endif
#define forn(i, n) for (int i = 0; i < (int)(n); i++)
typedef long long ll;
const int maxn = (int)3e5 + 10;
const int inf = (int)1e9;
struct tree
{
tree *l, *r;
int si, x, y, rev;
ll sum;
};
int tpos = 1;
tree t[maxn];
tree *Null = t;
inline void Calc( tree *t )
{
t->si = 1 + t->l->si + t->r->si;
t->sum = t->x + t->l->sum + t->r->sum;
}
inline void Down( tree *t )
{
if (t->rev)
{
if (t->l) t->l->rev ^= 1;
if (t->r) t->r->rev ^= 1;
swap(t->l, t->r), t->rev = 0;
}
}
tree *NewT( int x, int y )
{
tree *T = t + tpos++;
T->x = x, T->sum = x, T->y = y, T->si = 1;
T->l = T->r = Null;
return T;
}
void Split( tree *t, tree **l, tree **r, int num )
{
if (t == Null)
{
*l = *r = Null;
return;
}
Down(t);
if (t->l->si >= num)
Split(t->l, l, &t->l, num), Calc(*r = t);
else
Split(t->r, &t->r, r, num - t->l->si - 1), Calc(*l = t);
}
void Merge( tree **t, tree *l, tree *r )
{
if (l == Null || r == Null)
{
*t = max(l, r);
return;
}
if (l->y < r->y)
Down(*t = l), Merge(&(*t)->r, (*t)->r, r);
else
Down(*t = r), Merge(&(*t)->l, l, (*t)->l);
Calc(*t);
}
void Do( tree **t, int l, int r, int is, ll &sum )
{
tree *a, *b, *c, *tmp;
Split(*t, &a, &tmp, l);
Split(tmp, &b, &c, r - l);
sum = b->sum;
b->rev ^= is;
Merge(&tmp, a, b);
Merge(t, tmp, c);
}
void Add( tree **t, int x )
{
tree *r;
Merge(&r, *t, NewT(x, (rand() << 15) + rand()));
*t = r;
}
int main()
{
freopen("reverse.in", "r", stdin);
freopen("reverse.out", "w", stdout);
tree *t = Null;
int n, k, x;
scanf("%d%d", &n, &k);
srand((int)1e9 + 7);
forn(i, n)
scanf("%d", &x), Add(&t, x);
while (k--)
{
int l, r, type;
ll sum = 0;
scanf("%d%d%d", &type, &l, &r);
Do(&t, l - 1, r, type, sum);
if (!type)
printf(I64 "\n", sum);
}
return 0;
}