#include #include using namespace std; typedef long long LL; const int N = 100010; struct Node { int l, r, val, lcm, ma; LL sum; }; int n, q, a[N]; int GCD(int x, int y) { return y ? GCD(y, x % y) : x; } int LCM(int x, int y) { return x * y / GCD(x, y); } struct SegTree { Node seg[N << 2]; int Len(int u) { return seg[u].r - seg[u].l + 1; } void PushUp(int u) { seg[u].ma = max(seg[u << 1].ma, seg[u << 1 | 1].ma); seg[u].sum = seg[u << 1].sum + seg[u << 1 | 1].sum; seg[u].lcm = LCM(seg[u << 1].lcm, seg[u << 1 | 1].lcm); if (seg[u << 1].val && seg[u << 1].val == seg[u << 1 | 1].val) seg[u].val = seg[u << 1].val; else seg[u].val = 0; } void PushDown(int u) { if (seg[u].val) { seg[u << 1].ma= seg[u << 1].lcm = seg[u << 1].val = seg[u].val; seg[u << 1 | 1].ma = seg[u << 1 | 1].lcm = seg[u << 1 | 1].val = seg[u].val; seg[u << 1].sum = 1LL * seg[u].val * Len(u << 1); seg[u << 1 | 1].sum = 1LL * seg[u].val * Len(u << 1 | 1); seg[u].val = 0; } } void Build(int u, int l, int r) { seg[u] = { l, r, 0, 0, 0, 0LL }; if (l == r) { seg[u].val = seg[u].lcm = seg[u].ma = seg[u].sum = a[l]; return; } int mid = l + r >> 1; Build(u << 1, l, mid), Build(u << 1 | 1, mid + 1, r); PushUp(u); } void Modify(int u, int l, int r, int v) { if (l <= seg[u].l && seg[u].r <= r) { seg[u].ma = seg[u].lcm = seg[u].val = v; seg[u].sum = 1LL * v * Len(u); return; } PushDown(u); int mid = seg[u].l + seg[u].r >> 1; if (mid >= l) Modify(u << 1, l, r, v); if (mid + 1 <= r) Modify(u << 1 | 1, l, r, v); PushUp(u); } void ModifyGCD(int u, int l, int r, int v) { if (l <= seg[u].l && seg[u].r <= r) { if (seg[u].lcm && v % seg[u].lcm == 0) return; if (seg[u].val) { seg[u].ma = seg[u].lcm = seg[u].val = GCD(seg[u].val, v); seg[u].sum = 1LL * GCD(seg[u].val, v) * Len(u); return; } } PushDown(u); int mid = seg[u].l + seg[u].r >> 1; if (mid >= l) ModifyGCD(u << 1, l, r, v); if (mid + 1 <= r) ModifyGCD(u << 1 | 1, l, r, v); PushUp(u); } int QueryMax(int u, int l, int r) { if (l <= seg[u].l && seg[u].r <= r) return seg[u].ma; PushDown(u); int mid = seg[u].l + seg[u].r >> 1; int ret = 0; if (mid >= l) ret = max(ret, QueryMax(u << 1, l, r)); if (mid + 1 <= r) ret = max(ret, QueryMax(u << 1 | 1, l, r)); return ret; } LL QuerySum(int u, int l, int r) { if (l <= seg[u].l && seg[u].r <= r) return seg[u].sum; PushDown(u); int mid = seg[u].l + seg[u].r >> 1; LL ret = 0LL; if (mid >= l) ret += QuerySum(u << 1, l, r); if (mid + 1 <= r) ret += QuerySum(u << 1 | 1, l, r); return ret; } }; SegTree sgt; int main() { // freopen("gcdmax.in", "r", stdin); // freopen("gcdmax.out", "w", stdout); scanf("%d%d", &n, &q); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); sgt.Build(1, 1, n); while (q--) { int op; scanf("%d", &op); if (op == 1) { int l, r, x; scanf("%d%d%d", &l, &r, &x); sgt.Modify(1, l, r, x); } else if (op == 2) { int l, r, x; scanf("%d%d%d", &l, &r, &x); sgt.ModifyGCD(1, l, r, x); } else if (op == 3) { int l, r; scanf("%d%d", &l, &r); printf("%d\n", sgt.QueryMax(1, l, r)); } else { int l, r; scanf("%d%d", &l, &r); printf("%lld\n", sgt.QuerySum(1, l, r)); } } return 0; }