题目链接:POJ 3468
Description
You have integers, . You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
The first line contains two numbers and . .
The second line contains numbers, the initial values of . .
Each of the next lines represents an operation.
“” means adding c to each of . .
“” means querying the sum of .
Output
You need to answer all commands in order. One answer in a line.
1 2 3 4 5 6 7 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
Hint
The sums may exceed the range of 32-bit integers.
Solution 题意 给定 个数和 个询问,询问包含两种: 代表区间 的每个数加上 , 输出区间 的和。
题解 分块
区间更新模板题,本题可以使用树状数组、线段树和分块解决,这里使用的是分块。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 #include <cstdio> #include <iostream> #include <cmath> using namespace std ;typedef long long ll;const int maxn = 1e5 + 10 ;ll a[maxn], sum[maxn], add[maxn]; int L[maxn], R[maxn]; int block[maxn]; int n, q;int block_size; void init () { block_size = sqrt (n); for (int i = 1 ; i <= block_size; ++i) { L[i] = (i - 1 ) * block_size + 1 ; R[i] = i * block_size; } if (R[block_size] < n) { ++block_size; L[block_size] = R[block_size - 1 ] + 1 ; R[block_size] = n; } for (int i = 1 ; i <= block_size; ++i) { for (int j = L[i]; j <= R[i]; ++j) { block[j] = i; sum[i] += a[j]; } } } void change (int l, int r, ll c) { int p = block[l], q = block[r]; if (p == q) { for (int i = l; i <= r; ++i) { a[i] += c; } sum[p] += c * (r - l + 1 ); } else { for (int i = p + 1 ; i <= q - 1 ; ++i) { add[i] += c; } for (int i = l; i <= R[p]; ++i) { a[i] += c; } sum[p] += c * (R[p] - l + 1 ); for (int i = L[q]; i <= r; ++i) { a[i] += c; } sum[q] += c * (r - L[q] + 1 ); } } ll query (int l, int r) { int p = block[l], q = block[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 () { scanf ("%d%d" , &n, &q); for (int i = 1 ; i <= n; ++i) { scanf ("%lld" , &a[i]); } init(); for (int i = 0 ; i < q; ++i) { char op; getchar(); scanf ("%c" , &op); int l, r; scanf ("%d%d" , &l, &r); if (op == 'C' ) { ll c; scanf ("%lld" , &c); change(l, r, c); } else { printf ("%lld\n" , query(l, r)); } } return 0 ; }
Reference
《算法竞赛进阶指南》 李煜东 著
v1.5.2