P3372 【模板】线段树 1
线段树
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5+5; 5 ll a[maxn], add[maxn*4], sum[maxn*4]; 6 ll n, m; 7 void pushup(int rt) { 8 sum[rt] = sum[rt*2]+sum[rt*2+1]; 9 } 10 void pushdown(int rt, int l, int r) { 11 int mid = (l+r)/2; 12 sum[rt*2] = sum[rt*2]+add[rt]*(mid-l+1); 13 sum[rt*2+1] = sum[rt*2+1]+add[rt]*(r-mid); 14 add[rt*2] = add[rt*2]+add[rt]; 15 add[rt*2+1] = add[rt*2+1]+add[rt]; 16 17 add[rt] = 0; 18 } 19 void build(int l, int r, int rt) { 20 add[rt] = 0; 21 if (l == r) { 22 sum[rt] = a[l]; 23 return; 24 } 25 int mid = (l+r)/2; 26 build(l,mid,rt*2); 27 build(mid+1,r,rt*2+1); 28 pushup(rt); 29 } 30 void update(int be, int ed, int val, int l, int r, int rt) { 31 if (be <= l && r <= ed) { 32 add[rt] = add[rt]+val; 33 sum[rt] = sum[rt]+val*(r-l+1); 34 return; 35 } 36 pushdown(rt,l,r); 37 int mid = (l+r)/2; 38 if (be <= mid) update(be,ed,val,l,mid,rt*2); 39 if (ed > mid) update(be,ed,val,mid+1,r,rt*2+1); 40 pushup(rt); 41 } 42 ll query(int be, int ed, int l, int r, int rt) { 43 if (be <= l && r <= ed) { 44 return sum[rt]; 45 } 46 pushdown(rt,l,r); 47 ll res = 0; int mid = (l+r)/2; 48 if (be <= mid) res += query(be,ed,l,mid,rt*2); 49 if (ed > mid) res += query(be,ed,mid+1,r,rt*2+1); 50 return res; 51 } 52 int main() { 53 scanf("%d%d",&n,&m); 54 for (int i = 1; i <= n; i++) scanf("%lld",&a[i]); 55 build(1,n,1); 56 while (m--) { 57 int op, x, y; scanf("%d%d%d",&op,&x,&y); 58 if (op == 1) { 59 int k; scanf("%d",&k); 60 update(x,y,k,1,n,1); 61 } 62 else { 63 ll ans = query(x,y,1,n,1); 64 printf("%lld\n",ans); 65 } 66 } 67 return 0; 68 }
分块
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 typedef long long ll; 7 const int maxn = 1e5+5; 8 int L[maxn], R[maxn]; // 每个区间的范围 9 int pos[maxn]; // 记录所属块 10 ll sum[maxn], a[maxn]; 11 ll add[maxn]; // lazy标记 12 13 void change(int l, int r, int v) { 14 int p = pos[l], q = pos[r]; 15 if (p == q) { // 如果属于同一块 16 for (int i = l; i <= r; i++) a[i] += v; 17 sum[p] += (ll)(r-l+1)*v; 18 } 19 else { 20 for (int i = p+1; i <= q-1; i++) add[i] += v; // p和q中间的块的add 21 for (int i = l; i <= R[p]; i++) a[i] += v; 22 sum[p] += (ll)(R[p]-l+1)*v; 23 for (int i = L[q]; i <= r; i++) a[i] += v; 24 sum[q] += (ll)(r-L[q]+1)*v; 25 } 26 } 27 ll query(int l, int r) { 28 int p = pos[l], q = pos[r]; 29 ll ans = 0; 30 if (p == q) { 31 for (int i = l; i <= r; i++) ans += a[i]; 32 ans += add[p]*(r-l+1); 33 } 34 else { 35 for (int i = p+1; i <= q-1; i++) ans += sum[i] + add[i]*(R[i]-L[i]+1); 36 for (int i = l; i <= R[p]; i++) ans += a[i]; 37 ans += add[p]*(R[p]-l+1); 38 for (int i = L[q]; i <= r; i++) ans += a[i]; 39 ans += add[q]*(r-L[q]+1); 40 } 41 return ans; 42 } 43 44 int main() { 45 int n, q; scanf("%d%d",&n,&q); 46 for (int i = 1; i <= n; i++) scanf("%lld",&a[i]); 47 int t = sqrt(n); 48 for (int i = 1; i <= t; i++) { 49 L[i] = (i-1)*t + 1; 50 R[i] = i*t; 51 } 52 if (R[t] < n) t++, L[t] = R[t-1]+1, R[t] = n; 53 for (int i = 1; i <= t; i++) { 54 for (int j = L[i]; j <= R[i]; j++) { 55 pos[j] = i; 56 sum[i] += a[j]; 57 } 58 } 59 while (q--) { 60 int op, l, r, v; 61 scanf("%d",&op); 62 if (op == 2) { 63 scanf("%d%d",&l,&r); 64 printf("%lld\n",query(l,r)); 65 } 66 else { 67 scanf("%d%d%d",&l,&r,&v); 68 change(l,r,v); 69 } 70 } 71 return 0; 72 }