import sys import math input = sys.stdin.readline class SegTree: def __init__(self, a): sz = 1 while sz < len(a): sz <<= 1 self.sz = sz m = sz << 1 self.sm = [0] * m self.mn = [0] * m self.mx = [0] * m self.lz_set = [None] * m self.lz_add = [0] * m for i in range(sz): if i < len(a): val = a[i] else: val = 0 p = sz + i self.sm[p] = val self.mn[p] = val self.mx[p] = val for i in range(sz - 1, 0, -1): self.pull(i) def pull(self, i): lc = i << 1 rc = lc | 1 self.sm[i] = self.sm[lc] + self.sm[rc] self.mn[i] = min(self.mn[lc], self.mn[rc]) self.mx[i] = max(self.mx[lc], self.mx[rc]) def apply_set(self, i, l, r, v): self.sm[i] = v * (r - l) self.mn[i] = v self.mx[i] = v self.lz_set[i] = v self.lz_add[i] = 0 def apply_add(self, i, l, r, d): if d == 0: return self.sm[i] += d * (r - l) self.mn[i] += d self.mx[i] += d if self.lz_set[i] is not None: self.lz_set[i] += d else: self.lz_add[i] += d def push(self, i, l, r): if r - l == 1: self.lz_set[i] = None self.lz_add[i] = 0 return mid = (l + r) >> 1 lc = i << 1 rc = lc | 1 if self.lz_set[i] is not None: v = self.lz_set[i] self.apply_set(lc, l, mid, v) self.apply_set(rc, mid, r, v) self.lz_set[i] = None if self.lz_add[i] != 0: d = self.lz_add[i] self.apply_add(lc, l, mid, d) self.apply_add(rc, mid, r, d) self.lz_add[i] = 0 def update_set(self, ql, qr, v, i=1, l=0, r=None): if r is None: r = self.sz if qr <= l or r <= ql: return if ql <= l and r <= qr: self.apply_set(i, l, r, v) return self.push(i, l, r) mid = (l + r) >> 1 self.update_set(ql, qr, v, i << 1, l, mid) self.update_set(ql, qr, v, i << 1 | 1, mid, r) self.pull(i) def query_sum(self, ql, qr, i=1, l=0, r=None): if r is None: r = self.sz if qr <= l or r <= ql: return 0 if ql <= l and r <= qr: return self.sm[i] self.push(i, l, r) mid = (l + r) >> 1 left_sum = self.query_sum(ql, qr, i << 1, l, mid) right_sum = self.query_sum(ql, qr, i << 1 | 1, mid, r) return left_sum + right_sum def update_sqrt(self, ql, qr, i=1, l=0, r=None): if r is None: r = self.sz if qr <= l or r <= ql: return if self.mx[i] <= 1: return if ql <= l and r <= qr: d1 = math.isqrt(self.mn[i]) - self.mn[i] d2 = math.isqrt(self.mx[i]) - self.mx[i] if d1 == d2: self.apply_add(i, l, r, d1) return if r - l == 1: nv = math.isqrt(self.mx[i]) self.apply_set(i, l, r, nv) return self.push(i, l, r) mid = (l + r) >> 1 self.update_sqrt(ql, qr, i << 1, l, mid) self.update_sqrt(ql, qr, i << 1 | 1, mid, r) self.pull(i) def main(): n, q = map(int, input().split()) a = list(map(int, input().split())) seg = SegTree(a) ans = [] for _ in range(q): qry = list(map(int, input().split())) t = qry[0] if t == 0: l, r = qry[1], qry[2] ans.append(str(seg.query_sum(l, r))) elif t == 1: l, r, x = qry[1], qry[2], qry[3] seg.update_set(l, r, x) else: l, r = qry[1], qry[2] seg.update_sqrt(l, r) print("\n".join(ans)) if __name__ == "__main__": main()