记得分块还是大一时学的,后来就没怎么写过,趁此时机,再重新巩固一下此专题。
1.普通分块题目
后悔没有学习这么优秀的代码,自己当年写的就是一坨屎。
#include <cstdio> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int maxn = 1e5 + 50; int L[maxn], R[maxn]; ///每个区间范围 int pos[maxn]; ///记录所属块 ll sum[maxn], a[maxn]; ll add[maxn]; ///相当于lazy void change(int l, int r, int d) { int p = pos[l], q = pos[r]; if(p == q) ///所属同一块 { for(int i = l; i <= r; i++) a[i] += d; sum[p] += (ll)(r - l + 1) * d; } else ///不同块 { for(int i = p + 1; i <= q - 1; i++) add[i] += d; for(int i = l; i <= R[p]; i++) a[i] += d; sum[p] += (ll)(R[p] - l + 1) * d; for(int i = L[q]; i <= r; i++) a[i] += d; sum[q] += (ll)(r - L[q] + 1) * d; } } ll query(int l, int r) { int p = pos[l], q = pos[r]; ll ans = 0; if(p == q) ///同一块 { for(int i = l; i <= r; i++) ans += a[i]; ans += add[p] * (r - l + 1); } else ///不同块 { for(int i = p + 1; i <= q - 1; i++) ans += sum[i] + add[i] * (R[i] - L[i] + 1); for(int i = l; i <= R[p]; i++) ans += a[i]; ans += add[p] * (R[p] - l + 1); for(int i = L[q]; i <= r; i++) ans += a[i]; ans += add[q] * (r - L[q] + 1); } return ans; } int main() { int n, q; scanf("%d %d", &n, &q); for(int i = 1; i <= n; i++) scanf("%lld", &a[i]); int t = sqrt(n); for(int i = 1; i <= t; i++) { L[i] = (i - 1) * t + 1; R[i] = i * t; } if(R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n; ///即使剩下的比sqrt(n)大也无所谓 for(int i = 1; i <= t; i++) { for(int j = L[i]; j <= R[i]; j++) { pos[j] = i; sum[i] += a[j]; } } while(q--) { char s[5]; int l, r, v; scanf("%s", s); if(s[0] == 'Q') { scanf("%d %d", &l, &r); printf("%lld\n", query(l, r)); } else { scanf("%d %d %d", &l, &r, &v); change(l, r, v); } } return 0; }