树状数组 && 线段树
树状数组
支持单点修改
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> using namespace std; int n, m; int a[500001], c[500001]; int lowbit(int x) { return x & -x; } int sum(int x) { int ans = 0; while(x) { ans += c[x]; x -= lowbit(x); } return ans; } void add(int x, int d) { while(x <= n) { c[x] += d; x += lowbit(x); } } int main() { int i, j, x, y, z; scanf("%d %d", &n, &m); for(i = 1; i <= n; i++) { scanf("%d", &a[i]); add(i, a[i]); } for(i = 1; i <= m; i++) { scanf("%d %d %d", &z, &x, &y); if(z == 1) add(x, y); else printf("%d\n", sum(y) - sum(x - 1)); } return 0; }
支持区间修改
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <iostream> using namespace std; int n, m; long long c0[100001], c1[100001], a[100001]; long long lowbit(int x) {return x & -x;} long long sum(long long *c, int x) { long long ans = 0; while(x) { ans += c[x]; x -= lowbit(x); } return ans; } void add(long long *c, int x, int d) { while(x <= n) { c[x] += d; x += lowbit(x); } } int main() { int i, j, x, y, z, k; long long ans; scanf("%d%d", &n, &m); for(i = 1; i <= n; i++) { scanf("%d", &a[i]); add(c0, i, a[i]); } for(i = 1; i <= m; i++) { scanf("%d%d%d", &z, &x, &y); if(z == 1) { scanf("%d", &k); add(c0, x, -k * (x - 1)); add(c1, x, k); add(c0, y + 1, k * y); add(c1, y + 1, -k); } else { ans = 0; ans += sum(c0, y) + sum(c1, y) * y; ans -= sum(c0, x - 1) + sum(c1, x - 1) * (x - 1); printf("%lld\n", ans); } } return 0; }
线段树
支持区间修改
add[o]表示节点o的lazy标记,且节点o已经修改完
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define root 1, 1, N #define ls o << 1, l, m #define rs o << 1 | 1, m + 1, r int L, R; long long add[1500005], mul[1500005], c[1500005], P; inline int read() { int x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } inline void pushup(int o) { c[o] = (c[o << 1] + c[o << 1 | 1]) % P; } inline void build(int o, int l, int r) { add[o] = 0; mul[o] = 1; if(l == r) { scanf("%lld", &c[o]); return; } int m = (l + r) >> 1; build(ls); build(rs); pushup(o); } inline void pushdown(int o, int m) { if(add[o] == 0 && mul[o] == 1) return; c[o << 1] = (c[o << 1] * mul[o] + add[o] * (m - (m >> 1))) % P; c[o << 1 | 1] = (c[o << 1 | 1] * mul[o] + add[o] * (m >> 1)) % P; add[o << 1] = (add[o << 1] * mul[o] + add[o]) % P; add[o << 1 | 1] = (add[o << 1 | 1] * mul[o] + add[o]) % P; mul[o << 1] = (mul[o << 1] * mul[o]) % P; mul[o << 1 | 1] = (mul[o << 1 | 1] * mul[o]) % P; add[o] = 0; mul[o] = 1; } inline void update(int f, int d, int o, int l, int r) { if(L <= l && r <= R) { if(f == 2) { add[o] = (add[o] + d) % P; c[o] = (c[o] + d * (r - l + 1)) % P; } else { mul[o] = (mul[o] * d) % P; add[o] = (add[o] * d) % P; c[o] = (c[o] * d) % P; } return; } pushdown(o, r - l + 1); int m = (l + r) >> 1; if(L <= m) update(f, d, ls); if(m < R) update(f, d, rs); pushup(o); } inline long long query(int o, int l, int r) { if(L <= l && r <= R) return c[o]; pushdown(o, r - l + 1); int m = (l + r) >> 1; long long ret = 0; if(L <= m) ret += query(ls); if(m < R) ret += query(rs); return ret; } int main() { int N, Q; N = read(); P = read(); build(root); Q = read(); while(Q--) { int a, x, y, k; a = read(); if(a == 1 || a == 2) { x = read(); y = read(); k = read(); L = x; R = y; update(a, k, root); } else { x = read(); y = read(); L = x; R = y; printf("%lld\n", query(root) % P); } } return 0; }
ps:有意思的是这个代码还是[AHOI2009]维护序列的题解