Problem:
Score : 100 points

Problem Statement

You are given a binary array A=(A_1,A_2,\cdots,A_N) of length N.

Process Q queries of the following types. The i-th query is represented by three integers T_i,L_i,R_i.

T_i=1: Replace the value of A_j with 1-A_j for each L_i \leq j \leq R_i.

T_i=2: Calculate the inversion(*) of the array A_{L_i},A_{L_i+1},\cdots,A_{R_i}．

Note：The inversion of the array x_1,x_2,\cdots,x_k is the number of the pair of integers i,j with 1 \leq i < j \leq k, x_i > x_j.

Constraints

1 \leq N \leq 2 \times 10^5

0 \leq A_i \leq 1

1 \leq Q \leq 2 \times 10^5

1 \leq T_i \leq 2

1 \leq L_i \leq R_i \leq N

All values in Input are integer.

Input

Input is given from Standard Input in the following format:

N Q
A_1 A_2 \cdots A_N
T_1 L_1 R_1
T_2 L_2 R_2
\vdots
T_Q L_Q R_Q

Output

For each query with T_i=2, print the answer.

Sample Input 1

5 5
0 1 0 0 1
2 1 5
1 3 4
2 2 5
1 1 3
2 1 2

Sample Output 1

2
0
1

First query: Print 2, which is the inversion of (A_1,A_2,A_3,A_4,A_5)=(0,1,0,0,1).

Second query: Replace the value of A_3 and A_4 with 1 and 1, respectively.

Third query: Print 0, which is the inversion of (A_2,A_3,A_4,A_5)=(1,1,1,1).

Fourth query: Replace the value of A_1, A_2 and A_4 with 1, 0 and 0, respectively.

Fifth query: Print 1, which is the inversion of (A_1,A_2)=(1,0).

Solution in Ruby (2.7.1) (judge verdict: Time Limit Exceeded)

class Lazy_SegTree
    def initialize(v, e, id, &op)
        @n = v.size
        @e = e
        @id = id
        @op = op
        @log = (@n-1).bit_length
        @size = 1 << @log
        @d = Array.new(2 * @size, e)
        @lz = Array.new(@size, id)

        @n.times {|i| @d[@size + i] = v[i]}
        (@size - 1).downto(1) {|i| update(i)}
    end

    def set_mapping(&mapping); @mapping = mapping; end
    def set_composition(&composition); @composition = composition; end
    def update(k); @d[k] = @op.call(@d[2 * k], @d[2 * k + 1]); end

    def set(pos, x)
        pos += @size
        @log.downto(1) {|i| push(pos >> i)}
        @d[pos] = x
        1.upto(@log) {|i| update(pos >> i)}
    end

    def get(pos)
        pos += @size
        @log.downto(1) {|i| push(pos >> i)}
        @d[pos]
    end

    def push(k)
        all_apply(2 * k, @lz[k])
        all_apply(2 * k + 1, @lz[k])
        @lz[k] = @id
    end

    def prod(l, r)
        return @e if l == r
        l += @size
        r += @size

        @log.downto(1) do |i|
            push(l >> i) if (l >> i) << i != l
            push(r >> i) if (r >> i) << i != r
        end

        sml = smr = @e
        while l < r
            (sml = @op.call(sml, @d[l]); l += 1) if l[0] == 1
            smr = @op.call(@d[r -= 1], smr) if r[0] == 1
            l >>= 1
            r >>= 1
        end

        @op.call(sml, smr)
    end

    def all_prod; @d[1]; end

    def all_apply(k, f) 
        @d[k] = @mapping.call(f, @d[k])
        @lz[k] = @composition.call(f, @lz[k]) if k < @size
    end

    def apply(pos, f)
        pos += @size
        @log.downto(1) {|i| push(pos >> i)}
        @d[pos] = @mapping.call(f, @d[pos])
        1.upto(@log) {|i| update(pos >> i)}
    end

    def range_apply(l, r, f)
        return if l == r
        l += @size
        r += @size

        @log.downto(1) do |i|
            push(l >> i) if (l >> i) << i != l
            push((r - 1) >> i) if (r >> i) << i != r
        end

        l2, r2 = l, r
        while l < r
            (all_apply(l, f); l += 1) if l[0] == 1
            all_apply(r -= 1, f) if r[0] == 1
            l >>= 1
            r >>= 1
        end

        l, r = l2, r2
        1.upto(@log) do |i|
            update(l >> i) if (l >> i) << i != l
            update((r - 1) >> i) if (r >> i) << i != r
        end
    end

    def max_right(l, &g)
        return @n if l == @n
        l += @size
        @log.downto(1) {|i| push(l >> i)}
        sm = @e

        loop do
            l >>= 1 while l[0] == 0
            if !g.call(@op.call(sm, @d[l]))
                while l < @size
                    push(l)
                    l <<= 1
                    if g.call(@op.call(sm, @d[l]))
                        sm = @op.call(sm, @d[l])
                        l += 1
                    end
                end
                return l - @size
            end
            sm = @op.call(sm, @d[l])
            l += 1
            break if l & -l == l
        end
        return @n
    end

    def min_left(r, &g)
        return 0 if r == 0
        r += @size
        @log.downto(1) {|i| push((r - 1) >> i)}
        sm = @e

        loop do
            r -= 1
            r >>= 1 while r > 1 && r[0] == 1
            if !g.call(@op.call(@d[r], sm))
                while r < @size
                    push(r)
                    r = 2 * r + 1
                    if g.call(@op.call(@d[r], sm))
                        sm = @op.call(@d[r], sm)
                        r -= 1
                    end
                end
                return r + 1 - @size
            end
            sm = @op.call(@d[r], sm)
            break if r & -r == r
        end
        return 0
    end
end

n, q = gets.split.map(&:to_i)
a = gets.split.map{|e| e = e.to_i; [e ^ 1, e, 0]}

lst = Lazy_SegTree.new(a, [0,0,0], 0) {|x, y| [x[0] + y[0], x[1] + y[1], x[2] + y[2] + x[1] * y[0]]}
lst.set_mapping{|f, s| f == 0 ? s : [s[1], s[0], s[0] * s[1] - s[2]]}
lst.set_composition{|f1, f2| f1 ^ f2}

q.times do
    t, l, r = gets.split.map(&:to_i)

    if t == 1
        lst.range_apply(l-1, r, 1)
    else
        puts lst.prod(l-1, r)[2]
    end
end

__END__
@op : S * S -> S : 子の情報を元に親情報の更新する関数．左の子が第一引数
@mapping : F * S -> S : @lz に保存しておいた更新情報(F) を セグ木のノード(S) に反映する関数．S が葉ノードとは限らないことに注意
@composition : F * F -> F : 更新情報を伝搬させる関数（降りてきた情報が第一引数．今の情報は第二引数）???

@e : @op の底．つまり @op(e, x) = @op(x, e) = x
@id : @composition (? と @mapping) の底．つまり
    (? @mapping(id, x) = @mapping(x, id) = x かつ)
    @composition(id, x) = @composition(x, id) = x