#include <iostream>
#include <algorithm>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <list>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <bitset>
#include <random>
#include <complex>
#include <assert.h>

#include <atcoder/dsu.hpp>
#include <atcoder/fenwicktree.hpp>
#include <atcoder/segtree.hpp>
#include <atcoder/lazysegtree.hpp>
#include <atcoder/maxflow.hpp>
#include <atcoder/mincostflow.hpp>

using namespace std;
using namespace atcoder;

////////////////	型名など
typedef long long ll;
#define endl '\n'

////////////////	各種定数
const ll INF = 1LL << 60;
const double EPS = 1e-12;

////////////////	便利なテンプレート関数
template<typename T>
inline bool chmin(T& x, T a) {
	if (x >= a) { x = a; return true; }
	return false;
}

template<typename T>
inline bool chmax(T& x, T a) {
	if (x <= a) { x = a; return true; }
	return false;
}

////////////////	BIT
template <class T> struct BIT : fenwick_tree<T> {
	BIT() : fenwick_tree<T>() {}
	BIT(int n) : fenwick_tree<T>(n) {}
	BIT(const vector<T>& A) : fenwick_tree<T>((int)A.size()) {
		for (int i = 0; i < (int)A.size(); i++) {
			fenwick_tree<T>::add(i, A[i]);
		}
	}

	void get(int p) { return fenwick_tree<T>::sum(p, p + 1); }
	void set(int p, T x) { fenwick_tree<T>::add(p, x - get(p)); }
};

////////////////	セグ木

// #define SEGTREE_DATA_ADD			// 和をとるセグ木
// #define SEGTREE_DATA_MAX			// 最大値をとるセグ木
// #define SEGTREE_DATA_MIN			// 最小値をとるセグ木
#define SEGTREE_DATA_CLASS		// 要素がクラスで定義されたセグ木

#ifdef SEGTREE_DATA_ADD
using segtree_data_type = ll;
const segtree_data_type segtree_data_init_value = 0;
inline segtree_data_type segtree_data_merge(segtree_data_type a, segtree_data_type b) {// 要素aのbの和
	return a + b;
}
#endif
#ifdef SEGTREE_DATA_MAX
using segtree_data_type = ll;
const segtree_data_type segtree_data_init_value = -INF;
inline segtree_data_type segtree_data_merge(segtree_data_type a, segtree_data_type b) {// 要素aのbの最大値
	return max(a, b);
}
#endif
#ifdef SEGTREE_DATA_MIN
using segtree_data_type = ll;
const segtree_data_type segtree_data_init_value = INF;
inline segtree_data_type segtree_data_merge(segtree_data_type a, segtree_data_type b) {// 要素aのbの最小値
	return min(a, b);
}
#endif
#ifdef SEGTREE_DATA_CLASS
class segtree_data_class {
public:
	segtree_data_class() { zeros = 0, ones = 0, ans = 0; }

	void operator =(const segtree_data_class& other) {
		zeros = other.zeros;
		ones = other.ones;
		ans = other.ans;
	}
	void operator +=(segtree_data_class& other) {
		ans += other.ans + ones * other.zeros;
		zeros += other.zeros;
		ones += other.ones;
	}
	segtree_data_class operator +(segtree_data_class& other) {
		segtree_data_class d(*this); d += other; return d;
	}
	void operator ^=(ll x) {
		if (x == 0) { return; }
		ans = (zeros * ones - ans);
		ll temp = zeros; zeros = ones; ones = temp;
	}
	segtree_data_class operator ^(ll x) {
		segtree_data_class d(*this); d ^= x; return d;
	}
	ll zeros, ones, ans;
};

using segtree_data_type = segtree_data_class;
const segtree_data_type segtree_data_init_value = segtree_data_class();
inline segtree_data_type segtree_data_merge(segtree_data_type a, segtree_data_type b) {// 要素aのbのマージ
	return a + b;
}
#endif
segtree_data_type segtree_data_init() { return segtree_data_init_value; }

struct SegmentTree : segtree<segtree_data_type, segtree_data_merge, segtree_data_init> {
	SegmentTree() : segtree<segtree_data_type, segtree_data_merge, segtree_data_init>() {}
	SegmentTree(int n) : segtree<segtree_data_type, segtree_data_merge, segtree_data_init>(n) {}
	SegmentTree(const vector<segtree_data_type>& A) : segtree<segtree_data_type, segtree_data_merge, segtree_data_init>(A) {}
};


///////////////   遅延セグ木
using segtree_lazy_type = ll;

// #define SEGTREE_LAZY_SET			// 区間代入する遅延セグ木
// #define SEGTREE_LAZY_ADD			// 区間加算する遅延セグ木
#define SEGTREE_LAZY_XOR			// 区間XORする遅延セグ木
// #define SEGTREE_LAZY_MAX			// 最大値を更新する遅延セグ木
// #define SEGTREE_LAZY_MIN			// 最小値を更新する遅延セグ木

#ifdef SEGTREE_LAZY_SET
const segtree_lazy_type segtree_lazy_init_value = 0;
inline segtree_lazy_type segtree_lazy_merge(segtree_lazy_type a, segtree_lazy_type b) {// 演算子aとbのマージ
	return b;
}
inline segtree_data_type segtree_lazy_apply(segtree_lazy_type x, segtree_data_type a) {// aに演算子xを適用する
	return x;
}
#endif
#ifdef SEGTREE_LAZY_ADD
const segtree_lazy_type segtree_lazy_init_value = 0;
inline segtree_lazy_type segtree_lazy_merge(segtree_lazy_type a, segtree_lazy_type b) {// 演算子aとbのマージ
	return a + b;
}
inline segtree_data_type segtree_lazy_apply(segtree_lazy_type x, segtree_data_type a) {// aに演算子xを適用する
	return a + x;
}
#endif
#ifdef SEGTREE_LAZY_XOR
const segtree_lazy_type segtree_lazy_init_value = 0;
inline segtree_lazy_type segtree_lazy_merge(segtree_lazy_type a, segtree_lazy_type b) {// 演算子aとbのマージ
	return a ^ b;
}
inline segtree_data_type segtree_lazy_apply(segtree_lazy_type x, segtree_data_type a) {// aに演算子xを適用する
	return a ^ x;
}
#endif
#ifdef SEGTREE_LAZY_MAX
const segtree_lazy_type segtree_lazy_init_value = -INF;
inline segtree_lazy_type segtree_lazy_merge(segtree_lazy_type a, segtree_lazy_type b) {// 演算子aとbのマージ
	return max(a, b);
}
inline segtree_data_type segtree_lazy_apply(segtree_lazy_type x, segtree_data_type a) {// aに演算子xを適用する
	return max(a, x);
}
#endif
#ifdef SEGTREE_LAZY_MIN
const segtree_lazy_type segtree_lazy_init_value = INF;
inline segtree_lazy_type segtree_lazy_merge(segtree_lazy_type a, segtree_lazy_type b) {// 演算子aとbのマージ
	return min(a, b);
}
inline segtree_data_type segtree_lazy_apply(segtree_lazy_type x, segtree_data_type a) {// aに演算子xを適用する
	return min(a, x);
}
#endif
segtree_lazy_type segtree_lazy_init() { return segtree_lazy_init_value; }

struct LazySegmentTree : lazy_segtree<segtree_data_type, segtree_data_merge, segtree_data_init, segtree_lazy_type, segtree_lazy_apply, segtree_lazy_merge, segtree_lazy_init> {
	LazySegmentTree() : lazy_segtree<segtree_data_type, segtree_data_merge, segtree_data_init, segtree_lazy_type, segtree_lazy_apply, segtree_lazy_merge, segtree_lazy_init>() {}
	LazySegmentTree(int n) : lazy_segtree<segtree_data_type, segtree_data_merge, segtree_data_init, segtree_lazy_type, segtree_lazy_apply, segtree_lazy_merge, segtree_lazy_init>(n) {}
	LazySegmentTree(const vector<segtree_data_type>& A) : lazy_segtree<segtree_data_type, segtree_data_merge, segtree_data_init, segtree_lazy_type, segtree_lazy_apply, segtree_lazy_merge, segtree_lazy_init>(A) {}
};

int main() {
	ll N, Q; cin >> N >> Q;
	vector<segtree_data_class> A(N);
	for (int i = 0; i < N; i++) {
		int a; cin >> a;
		if (a == 1) { A[i].ones++; }
		else { A[i].zeros++; }
	}
	LazySegmentTree LST(A);
	for (int q = 0; q < Q; q++) {
		ll T, L, R; cin >> T >> L >> R; L--;
		if (T == 1) {
			LST.apply(L, R, 1);
		}
		else {
			cout << LST.prod(L, R).ans << endl;
		}
	}

	return 0;
}

Measured memory_bytes: 22276