提交时间:2024-11-12 12:37:00

运行 ID: 34585

#include <algorithm> #include <cstdio> #include <cstdlib> #include <vector> using namespace std; using i64 = long long; constexpr int MOD = 1e9 + 7; inline int mod(i64 x) { return (x % MOD + MOD) % MOD; } inline int mod_add(int x, int y) { return mod(x + y); } inline int mod_mul(int x, int y) { return mod((i64)x * y); } inline int sq(int x) { return mod_mul(x, x); } inline int divide(int numer, int denom) { static const auto sgn = [](int x) { return x >= 0 ? 1 : (x < 0 ? -1 : 0); }; return numer / denom - (int)(numer % denom != 0 && sgn(numer) != sgn(denom)); } struct SegTree { struct Node { int l, r, sum, sq_sum, mx, mn; int size() { return r - l + 1; } int mid() { return (l + r) >> 1; } bool in(int lo, int hi) { return lo <= l && r <= hi; } }; vector<Node> tree; vector<int> orig; SegTree(const vector<int>& arr) : tree(arr.size() << 3) , orig(arr) { build(1, arr.size()); } void modify(int idx, int val, int pos = 1) { if (tree[pos].in(idx, idx)) { tree[pos].sq_sum = sq(val); tree[pos].mn = tree[pos].mx = tree[pos].sum = val; return; } int mid = tree[pos].mid(); if (idx <= mid) modify(idx, val, pos << 1); else modify(idx, val, pos << 1 | 1); pushup(pos); } void update(int l, int r, int val, int pos = 1) { if ((tree[pos].mx <= 0 && tree[pos].mn >= -1 && val > 0) || (tree[pos].mx == 0 && tree[pos].mn == 0 && val < 0)) return; else if (tree[pos].size() == 1) { tree[pos].mn = tree[pos].mx = tree[pos].sum = divide(tree[pos].sum, val); tree[pos].sq_sum = sq(tree[pos].sum); return; } int mid = tree[pos].mid(); if (l <= mid) update(l, r, val, pos << 1); if (r > mid) update(l, r, val, pos << 1 | 1); pushup(pos); } int query_sum(int l, int r, int pos = 1) { if (tree[pos].mx == 0 && tree[pos].mn == 0) return 0; else if (tree[pos].in(l, r)) return mod(tree[pos].sum); int mid = tree[pos].mid(), res = 0; if (l <= mid) res = mod_add(res, query_sum(l, r, pos << 1)); if (r > mid) res = mod_add(res, query_sum(l, r, pos << 1 | 1)); return res; } int query_sq(int l, int r, int pos = 1) { if (tree[pos].mx == 0 && tree[pos].mn == 0) return 0; else if (tree[pos].in(l, r)) return mod(tree[pos].sq_sum); int mid = tree[pos].mid(), res = 0; if (l <= mid) res = mod_add(res, query_sq(l, r, pos << 1)); if (r > mid) res = mod_add(res, query_sq(l, r, pos << 1 | 1)); return res; } private: void build(int l, int r, int pos = 1) { tree[pos].l = l; tree[pos].r = r; if (l == r) { tree[pos].mn = tree[pos].mx = tree[pos].sum = orig[l - 1]; tree[pos].sq_sum = sq(orig[l - 1]); return; } int mid = (l + r) >> 1; build(l, mid, pos << 1); build(mid + 1, r, pos << 1 | 1); pushup(pos); } void pushup(int pos) { tree[pos].sq_sum = mod_add(tree[pos << 1].sq_sum, tree[pos << 1 | 1].sq_sum); tree[pos].sum = mod_add(tree[pos << 1].sum, tree[pos << 1 | 1].sum); tree[pos].mx = max(tree[pos << 1].mx, tree[pos << 1 | 1].mx); tree[pos].mn = min(tree[pos << 1].mn, tree[pos << 1 | 1].mn); } }; int main() { // freopen("sequence.in", "r", stdin); // freopen("sequence.out", "w", stdout); int n, q; scanf("%d %d", &n, &q); vector<int> arr(n); for (auto& x : arr) scanf("%d", &x); SegTree tree(arr); while (q-- > 0) { int op, l, r; scanf("%d %d %d", &op, &l, &r); if (op == 1) printf("%d\n", tree.query_sum(l, r)); else if (op == 2) printf("%d\n", tree.query_sq(l, r)); else if (op == 3) { int p; scanf("%d", &p); tree.update(l, r, p); } else if (op == 4) tree.modify(l, r); } return 0; }