#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;

template<typename Monoid,typename OperatorMonoid,typename F,typename G,typename H>
class LazySegmentTree {
private:
    int sz,height;
    vec<Monoid> data;
    vec<OperatorMonoid> lazy;
    const F op;
    const G homo;
    const H comp;
    const Monoid e;
    const OperatorMonoid Oe;
public:
    LazySegmentTree(int n,const F op,const G homo,const H comp,
                    const Monoid &e,const OperatorMonoid Oe)
        : op(op),homo(homo),comp(comp),e(e),Oe(Oe) {
        sz = 1;
        height = 0;
        while(sz<=n) sz <<= 1,height++;
        data.assign(2*sz,e);
        lazy.assign(2*sz,Oe);
    }

    void set(int k,const Monoid &x) {
        data[k+sz] = x;
    }

    void build() {
        for(int k=sz-1;k>0;k--) {
            data[k] = op(data[2*k], data[2*k+1]);
        }
    }

    inline void propagate(int k) {
        if(lazy[k]!=Oe) {
            lazy[2*k] = comp(lazy[2*k], lazy[k]);
            lazy[2*k+1] = comp(lazy[2*k+1], lazy[k]);
            data[k] = reflect(k);
            lazy[k] = Oe;
        }
    }

    inline Monoid reflect(int k) {
        return lazy[k] == Oe? data[k]:homo(data[k],lazy[k]);
    }

    inline void recalc(int k) {
        while(k>>=1) data[k] = op(reflect(2*k), reflect(2*k+1));
    }

    inline void thrust(int k) {
        for(int i=height;i>0;i--) propagate(k>>i);
    }

    void update(int a, int b, const OperatorMonoid &x) {
        thrust(a+=sz);
        thrust(b+=sz-1);
        for(int l=a,r=b+1;l<r;l>>=1,r>>=1) {
            if(l&1) lazy[l] = comp(lazy[l],x),++l;
            if(r&1) --r, lazy[r] = comp(lazy[r],x);
        }
        recalc(a);
        recalc(b);
    }

    Monoid query(int a, int b) {
        thrust(a+=sz);
        thrust(b+=sz-1);
        Monoid L = e, R = e;
        for(int l=a, r=b+1;l<r;l>>= 1,r>>=1) {
            if(l&1) L = op(L,reflect(l++));
            if(r&1) R = op(reflect(--r),R);
        }
        return op(L,R);
    }

    Monoid operator[](const int &k) {
        return query(k,k+1);
    }
};

using arr = array<ll,2>;

struct state{
    arr cnt;
    arr res;
};

auto op = [](state L,state R){
    arr cnt{},res{};
    for(int k=0;k<2;k++) cnt[k] = L.cnt[k]+R.cnt[k];
    for(int k=0;k<2;k++) res[k] = L.res[k]+R.res[k];
    res[0] += L.cnt[0]*R.cnt[1];
    res[1] += L.cnt[1]*R.cnt[0];
    return (state) {cnt,res};
};

auto func = [](state S,int x){
    if(x==1){
        swap(S.cnt[0],S.cnt[1]);
        swap(S.res[0],S.res[1]);
    }
    return S;
};

auto comp = [](int x,int y){return x^y;};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N,Q;
    cin >> N >> Q;
    LazySegmentTree seg(N,op,func,comp,(state){{0,0},{0,0}},0);
    for(int i=0;i<N;i++){
        int a;
        cin >> a;
        if(a==0) seg.set(i,(state){{1,0},{0,0}});
        else seg.set(i,(state){{0,1},{0,0}});
    }
    seg.build();
    while(Q--){
        int t,l,r;
        cin >> t >> l >> r;
        l--,r--;
        if(t==1){
            seg.update(l,r+1,1);
        }else{
            auto S = seg.query(l,r+1);
            cout << S.res[1] << "\n";
        }
    }
}

Measured memory_bytes: 21644