#include using namespace std; using lint = long long int; using pint = pair; using plint = pair; struct fast_ios { fast_ios(){ cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_; #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((lint)(x).size()) #define POW2(n) (1LL << (n)) #define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i=i##_begin_;i--) #define REP(i, n) FOR(i,0,n) #define IREP(i, n) IFOR(i,0,n) template void ndarray(vector &vec, int len) { vec.resize(len); } template void ndarray(vector &vec, int len, Args... args) { vec.resize(len); for (auto &v : vec) ndarray(v, args...); } template bool mmax(T &m, const T q) { if (m < q) {m = q; return true;} else return false; } template bool mmin(T &m, const T q) { if (m > q) {m = q; return true;} else return false; } template pair operator+(const pair &l, const pair &r) { return make_pair(l.first + r.first, l.second + r.second); } template pair operator-(const pair &l, const pair &r) { return make_pair(l.first - r.first, l.second - r.second); } template istream &operator>>(istream &is, vector &vec){ for (auto &v : vec) is >> v; return is; } ///// This part below is only for debug, not used ///// template ostream &operator<<(ostream &os, const vector &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; } template ostream &operator<<(ostream &os, const deque &vec){ os << "deq["; for (auto v : vec) os << v << ","; os << "]"; return os; } template ostream &operator<<(ostream &os, const set &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template ostream &operator<<(ostream &os, const unordered_set &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template ostream &operator<<(ostream &os, const multiset &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template ostream &operator<<(ostream &os, const unordered_multiset &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template ostream &operator<<(ostream &os, const pair &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; } template ostream &operator<<(ostream &os, const map &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; } template ostream &operator<<(ostream &os, const unordered_map &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; } #define dbg(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl; ///// END ///// /* #include #include #include using namespace __gnu_pbds; // find_by_order(), order_of_key() template using pbds_set = tree, rb_tree_tag, tree_order_statistics_node_update>; template using pbds_map = tree, rb_tree_tag, tree_order_statistics_node_update>; */ constexpr lint INF = 1e9 + 100; struct Node { int n; lint max_val; lint total_sum; lint lca; Node(int n = 0, int max_val = 0, lint total_sum = 0, lint lca = 1) : n(n), max_val(max_val), total_sum(total_sum), lca(lca) {} }; constexpr int UPDATE = 1; constexpr int GCD = 2; constexpr int MAXVAL = 3; constexpr int SUM = 4; struct LazySegTree { using T_NODE = Node; using T_DELAY = plint; // using T_QUERY = lint; using T_RETVAL = T_NODE; T_NODE zero_node = Node(); T_DELAY zero_delay = plint(0, 0); T_RETVAL zero_retval = Node(); int N; int head; vector val; vector dval; void merge_node(int pos) { int l = pos * 2 + 1, r = pos * 2 + 2; // Calculate val[pos] from its children val[pos * 2 + 1], val[pos * 2 + 2] val[pos].n = val[l].n + val[r].n; val[pos].max_val = max(val[l].max_val, val[r].max_val); val[pos].total_sum = val[l].total_sum + val[r].total_sum; val[pos].lca = min(INF, val[l].lca * val[r].lca / __gcd(val[l].lca, val[r].lca)); } void reflect_delay(int pos) { // Reflect delay information dval[pos] to val[pos] if (dval[pos].second == UPDATE) { val[pos] = Node(val[pos].n, dval[pos].first, dval[pos].first * val[pos].n, dval[pos].first); } if (dval[pos].second == GCD) { if (val[pos].lca < INF and dval[pos].first % val[pos].lca == 0) return; if (pos < head) { pushdown_dval(pos * 2 + 1, dval[pos]); resolve_dval(pos * 2 + 1); pushdown_dval(pos * 2 + 2, dval[pos]); resolve_dval(pos * 2 + 2); merge_node(pos); } else { lint x = val[pos].total_sum; lint xnew = __gcd(x, dval[pos].first); val[pos] = Node(1, xnew, xnew, xnew); } } } void pushdown_dval(int child_pos, const T_DELAY &d) { // operate d to dval[child_pos] if (d.second == UPDATE or dval[child_pos].second == 0) dval[child_pos] = d; else if (d.second == GCD) { dval[child_pos].first = __gcd(dval[child_pos].first, d.first); } } T_RETVAL merge_retval(const T_RETVAL &l, const T_RETVAL &r) { T_RETVAL ret; ret.n = l.n + r.n; ret.max_val = max(l.max_val, r.max_val); ret.total_sum = l.total_sum + r.total_sum; return ret; } ////// general description ////// LazySegTree(const vector &val_init) : N(val_init.size()) { int N_tmp = 1; while (N_tmp < N) N_tmp <<= 1; val.assign(N_tmp * 2, zero_node); dval.assign(N_tmp * 2, zero_delay); head = N_tmp - 1; copy(val_init.begin(), val_init.end(), val.begin() + head); for (int pos = head - 1; pos >= 0; pos--) { merge_node(pos); } } void resolve_dval(int pos) { // posで遅延を解消して子孫に押し付ける reflect_delay(pos); if (pos < head and dval[pos] != zero_delay) { pushdown_dval(pos * 2 + 1, dval[pos]); pushdown_dval(pos * 2 + 2, dval[pos]); dval[pos] = zero_delay; } } void update(int begin, int end, T_DELAY delay) { update(begin, end, delay, 0, 0, head + 1); } void update(int begin, int end, T_DELAY delay, int pos, int l, int r) { // Operate delay to the node pos // After this, dval[pos] must be zero if (begin <= l and r <= end) { // Update whole [l, r) by delay pushdown_dval(pos, delay); resolve_dval(pos); } else if (begin < r and l < end) { // Update somewhere in [l, r) resolve_dval(pos); update(begin, end, delay, pos * 2 + 1, l, (l + r) / 2); update(begin, end, delay, pos * 2 + 2, (l + r) / 2, r); merge_node(pos); } else resolve_dval(pos); } T_RETVAL getvalue(int begin, int end) { return getvalue(begin, end, 0, 0, head + 1); } T_RETVAL getvalue(int begin, int end, int pos, int l, int r) { resolve_dval(pos); if (begin <= l and r <= end) return val[pos]; else if (begin < r and l < end) { T_RETVAL vl = getvalue(begin, end, pos * 2 + 1, l, (l + r) / 2); T_RETVAL vr = getvalue(begin, end, pos * 2 + 2, (l + r) / 2, r); return merge_retval(vl, vr); } else return zero_retval; } }; int main() { int N, Q; cin >> N >> Q; vector A(N); REP(i, N) { int a; cin >> a; A[i] = Node(1, a, a, a); } LazySegTree st(A); REP(_, Q) { int q, l, r; cin >> q >> l >> r; l--; if (q == UPDATE) { lint x; cin >> x; st.update(l, r, plint(x, UPDATE)); } if (q == GCD) { lint x; cin >> x; st.update(l, r, plint(x, GCD)); } if (q == MAXVAL) { cout << st.getvalue(l, r).max_val << endl; } if (q == SUM) { cout << st.getvalue(l, r).total_sum << endl; } } }