import sys input = sys.stdin.buffer.readline sys.setrecursionlimit(10 ** 7) #data: (left, right, val) u_data = (-1, -1, 0) u_lazy = 0 def op_data(A, B): la, ra, va = A lb, rb, vb = B if la == ra == -1: return B if lb == rb == -1: return A return la, rb, va + vb + int(ra != lb) def op_lazy(A, B): return A + B def op_merge(L, D): return D[0] + L, D[1] + L, D[2] class LazySegmetTree: def __init__(self, size, op_data, u_data, op_lazy, u_lazy, op_merge): """ size: 元の配列の長さ op_data(Ldata, Rdata), u_data: クエリ関数、単位元 op_lazy(Llazy, Rlazy), u_lazy: 遅延作用の関数、単位元 op_merge(lazy, data): dataとlazyとの演算 """ self.N = size self.op_data = op_data self.op_lazy = op_lazy self.op_merge = op_merge self.u_data = u_data self.u_lazy = u_lazy self.data = [u_data] * (2 * self.N) self.lazy = [u_lazy] * (2 * self.N) def initialize(self, arr): op = self.op_data for i, a in enumerate(arr, self.N): self.data[i] = a for i in reversed(range(1, self.N)): self.data[i] = op(self.data[i << 1], self.data[i << 1 | 1]) def show(self): print("show array") for i in range(self.N): print(self.fold(i, i+1), end=" ") print("\n") def _propagate_top_down(self, L): op = self.op_lazy merge = self.op_merge unit = self.u_lazy for i in reversed(range(1, L.bit_length())): i = L >> i v = self.lazy[i] if v == unit: continue self.data[i] = merge(v, self.data[i]) self.lazy[i << 1] = op(v, self.lazy[i << 1]) self.lazy[i << 1 | 1] = op(v, self.lazy[i << 1 | 1]) self.lazy[i] = unit def _propagate_bottom_up(self, i): merge = self.op_merge op = self.op_data while i > 1: i >>= 1 self.data[i] = op(merge(self.lazy[i << 1], self.data[i << 1]), merge(self.lazy[i << 1 | 1], self.data[i << 1 | 1])) def fold(self, L, R): resL = self.u_data resR = self.u_data op = self.op_data merge = self.op_merge L += self.N R += self.N L0 = L // (L & -L) R0 = R // (R & -R) - 1 self._propagate_top_down(L0) self._propagate_top_down(R0) while L < R: if L & 1: resL = op(resL, merge(self.lazy[L], self.data[L])) L += 1 if R & 1: R -= 1 resR = op(merge(self.lazy[R], self.data[R]), resR) L >>= 1 R >>= 1 return op(resL, resR) def update(self, i, val): # 未調整 i += self.N i0 = i // (i & -i) self._propagate_top_down(i0) self.data[i] = self.op_merge(self.lazy[i], self.data[i]) self.data[i] = self.op_data(val, self.data[i]) self.lazy[i] = self.u_lazy self._propagate_bottom_up(i0) def range_update(self, L, R, val): op = self.op_lazy L += self.N R += self.N L0 = L // (L & -L) R0 = R // (R & -R) - 1 self._propagate_top_down(L0) self._propagate_top_down(R0) while L < R: if L & 1: self.lazy[L] = op(val, self.lazy[L]) L += 1 if R & 1: R -= 1 self.lazy[R] = op(val, self.lazy[R]) L >>= 1 R >>= 1 self._propagate_bottom_up(L0) self._propagate_bottom_up(R0) N, Q = map(int, input().split()) arr = [(a, a, 0) for a in map(int, input().split())] seg = LazySegmetTree(N, op_data, u_data, op_lazy, u_lazy, op_merge) seg.initialize(arr) for _ in range(Q): t, *arg = map(int, input().split()) if t == 1: l, r, x = arg seg.range_update(l - 1, r, x) else: l, r = arg print(seg.fold(l - 1, r)[2] + 1)