1 条题解
-
0
两种修改用一个
update
#include <bits/stdc++.h> #define int long long using namespace std; const int MAXN = 100000; int n, m, mod; int a[MAXN + 5]; int t[MAXN * 4 + 5]; int lazy_add[MAXN * 4 + 5], lazy_mul[MAXN * 4 + 5]; void down(int now, int l, int r) { int mid = (l + r) / 2; int add = lazy_add[now]; int mul = lazy_mul[now]; // 传 mul if (mul != 1) { t[now * 2] *= mul; lazy_mul[now * 2] *= mul; lazy_add[now * 2] *= mul; t[now * 2 + 1] *= mul; lazy_mul[now * 2 + 1] *= mul; lazy_add[now * 2 + 1] *= mul; } // 传 add if (add != 0) { t[now * 2] += (mid - l + 1) * add; lazy_add[now * 2] += add; t[now * 2 + 1] += (r - mid) * add; lazy_add[now * 2 + 1] += add; } // mod t[now * 2] %= mod; lazy_mul[now * 2] %= mod; lazy_add[now * 2] %= mod; t[now * 2 + 1] %= mod; lazy_mul[now * 2 + 1] %= mod; lazy_add[now * 2 + 1] %= mod; // clear lazy_add[now] = 0; lazy_mul[now] = 1; } void build(int now, int l, int r) { lazy_mul[now] = 1; lazy_add[now] = 0; if (l == r) { t[now] = a[l]; return; } int mid = (l + r) / 2; build(now * 2, l, mid); build(now * 2 + 1, mid + 1, r); t[now] = (t[now * 2] + t[now * 2 + 1]) % mod; } void update(int now, int l, int r, int x, int y, int mul, int add) { if (x <= l && r <= y) { t[now] *= mul; lazy_mul[now] *= mul; lazy_add[now] *= mul; t[now] += (r - l + 1) * add; lazy_add[now] += add; t[now] %= mod; lazy_mul[now] %= mod; lazy_add[now] %= mod; return; } down(now, l, r); int mid = (l + r) / 2; if (x <= mid) update(now * 2, l, mid, x, y, mul, add); if (y > mid) update(now * 2 + 1, mid + 1, r, x, y, mul, add); t[now] = (t[now * 2] + t[now * 2 + 1]) % mod; } int query(int now, int l, int r, int x, int y) { if (x <= l && r <= y) return t[now]; down(now, l, r); int mid = (l + r) / 2; int res = 0; if (x <= mid) res = (res + query(now * 2, l, mid, x, y)) % mod; if (y >= mid + 1) res = (res + query(now * 2 + 1, mid + 1, r, x, y)) % mod; return res; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> mod; for (int i = 1; i <= n; i++) cin >> a[i]; build(1, 1, n); for (int i = 1; i <= m; i++) { int op, x, y, z; cin >> op; if (op == 1) { cin >> x >> y >> z; update(1, 1, n, x, y, z, 0); } if (op == 2) { cin >> x >> y >> z; update(1, 1, n, x, y, 1, z); } if (op == 3) { cin >> x >> y; cout << query(1, 1, n, x, y) << "\n"; } } return 0; }
两个修改用两个
update
#include <bits/stdc++.h> #define int long long using namespace std; const int MAXN = 100000; int n, m, p; int a[MAXN + 5]; // 线段树:单点修改、区间查询(区间和) int t[4 * MAXN + 5]; int lazyAdd[4 * MAXN + 5], lazyMul[4 * MAXN + 5]; // 基于a[]建线段树 void build(int now, int l, int r) { lazyAdd[now] = 0; lazyMul[now] = 1; if (l == r) { t[now] = a[l]; return; } int mid = (l + r) / 2; build(now * 2, l, mid); build(now * 2 + 1, mid + 1, r); t[now] = t[now * 2] + t[now * 2 + 1]; t[now] %= p; } void down(int now, int l, int r) { int mid = (l + r) / 2; // 左子树 now*2,l,mid // 右子树 now*2+1,mid+1,r int add = lazyAdd[now]; int mul = lazyMul[now]; lazyMul[now * 2] *= mul; lazyMul[now * 2] %= p; lazyAdd[now * 2] *= mul; lazyAdd[now * 2] %= p; t[now * 2] *= mul; t[now * 2] %= p; lazyAdd[now * 2] += add; lazyAdd[now * 2] %= p; t[now * 2] += (mid - l + 1) * add; t[now * 2] %= p; lazyMul[now * 2 + 1] *= mul; lazyMul[now * 2 + 1] %= p; lazyAdd[now * 2 + 1] *= mul; lazyAdd[now * 2 + 1] %= p; t[now * 2 + 1] *= mul; t[now * 2 + 1] %= p; lazyAdd[now * 2 + 1] += add; lazyAdd[now * 2 + 1] %= p; t[now * 2 + 1] += (r - mid) * add; t[now * 2 + 1] %= p; lazyAdd[now] = 0; lazyMul[now] = 1; } // 当前做到了树上的now号节点,当前节点对应的区间为 [l,r] // 需要给 [x,y] 这些数都加 z void update_add(int now, int l, int r, int x, int y, int z) { if (x <= l && r <= y) { t[now] += (r - l + 1) * z; t[now] %= p; lazyAdd[now] += z; lazyAdd[now] %= p; return; } int mid = (l + r) / 2; // 左子树 now*2,l,mid // 右子树 now*2+1,mid+1,r down(now, l, r); // 把之前欠的结清 if (x <= mid) update_add(now * 2, l, mid, x, y, z); if (y > mid) update_add(now * 2 + 1, mid + 1, r, x, y, z); t[now] = t[now * 2] + t[now * 2 + 1]; t[now] %= p; } void update_mul(int now, int l, int r, int x, int y, int z) { if (x <= l && r <= y) { t[now] *= z; t[now] %= p; lazyMul[now] *= z; lazyMul[now] %= p; lazyAdd[now] *= z; lazyAdd[now] %= p; return; } int mid = (l + r) / 2; // 左子树 now*2,l,mid // 右子树 now*2+1,mid+1,r down(now, l, r); // 把之前欠的结清 if (x <= mid) update_mul(now * 2, l, mid, x, y, z); if (y > mid) update_mul(now * 2 + 1, mid + 1, r, x, y, z); t[now] = t[now * 2] + t[now * 2 + 1]; t[now] %= p; } int query(int now, int l, int r, int x, int y) { //[l,r] 是 [x,y] 的子区间 if (x <= l && r <= y) return t[now]; int mid = (l + r) / 2; // 左子树 now*2,l,mid // 右子树 now*2+1,mid+1,r down(now, l, r); // 把之前欠的结清 int res = 0; if (x <= mid) res += query(now * 2, l, mid, x, y); if (y > mid) res += query(now * 2 + 1, mid + 1, r, x, y); return res % p; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> p; for (int i = 1; i <= n; i++) { cin >> a[i]; } build(1, 1, n); while (m--) { int op, x, y, z; cin >> op; if (op == 1) { cin >> x >> y >> z; update_mul(1, 1, n, x, y, z); } else if (op == 2) { cin >> x >> y >> z; update_add(1, 1, n, x, y, z); } else if (op == 3) { cin >> x >> y; // cout sum(a[x]~a[y]) cout << query(1, 1, n, x, y) << "\n"; } } return 0; }
- 1
信息
- ID
- 3617
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 27
- 已通过
- 13
- 上传者