LOJ6280. 數列分塊入門 4 題解
阿新 • • 發佈:2021-11-08
涉及操作:
- 區間加法;
- 區間求和。
解題思路:
數列分塊。
需要:
- \(sum_i\) 表示第 \(i\) 個分塊單獨累加的數值和;
- \(tag_i\) 表示第 \(i\) 個分塊整體累加的數值和(就是分塊 \(i\) 內的每個數都會增加 \(tag_i\))。
示例程式:
#include <bits/stdc++.h> using namespace std; const int maxn = 50050; int n, blo, bl[maxn]; long long a[maxn], sum[505], tag[505]; /** tag[i]記錄第i個分塊的數值和 sum[i]第i個塊所有單獨增加的元素和 */ void add(int l, int r, long long val) { for (int i = l; i <= min(bl[l]*blo, r); i ++) a[i] += val, sum[bl[i]] += val; if (bl[l] != bl[r]) for (int i = (bl[r]-1)*blo+1; i <= r; i ++) a[i] += val, sum[bl[i]] += val; for (int i = bl[l]+1; i < bl[r]; i ++) tag[i] += val; } long long query(int l, int r, long long M) { long long ans = 0; for (int i = l; i <= min(bl[l]*blo, r); i ++) ans += a[i] + tag[bl[i]]; if (bl[l] != bl[r]) for (int i = (bl[r]-1)*blo+1; i <= r; i ++) ans += a[i] + tag[bl[i]]; for (int i = bl[l]+1; i < bl[r]; i ++) ans += sum[i] + tag[i] * blo; return (ans % M + M) % M; } int main() { ios::sync_with_stdio(0); cin >> n; blo = sqrt(n); for (int i = 1; i <= n; i ++) { cin >> a[i]; bl[i] = (i - 1) / blo + 1; sum[bl[i]] += a[i]; } for (int i = 0; i < n; i ++) { int op, l, r, c; cin >> op >> l >> r >> c; if (op == 0) add(l, r, c); else cout << query(l, r, c+1) << endl; } return 0; }