Description
You have N integers, A1, A2, ... , AN. 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.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
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
4 55 9 15
Hint
Source
1 /* 2 宋代陆游 3 《临安春雨初霁》 4 5 世味年来薄似纱,谁令骑马客京华。 6 小楼一夜听春雨,深巷明朝卖杏花。 7 矮纸斜行闲作草,晴窗细乳戏分茶。 8 素衣莫起风尘叹,犹及清明可到家。 9 */ 10 #include <iostream> 11 #include <cstdio> 12 #include <algorithm> 13 #include <cstring> 14 #include <vector> 15 #include <utility> 16 #include <iomanip> 17 #include <string> 18 #include <cmath> 19 #include <queue> 20 #include <assert.h> 21 #include <map> 22 #include <ctime> 23 #include <cstdlib> 24 #include <stack> 25 #define LOCAL 26 const int INF = 0x7fffffff; 27 const int MAXN = 100000 + 10; 28 const int maxnode = 300000; 29 using namespace std; 30 struct Node{ 31 int l, r; 32 long long sum, d; 33 }tree[maxnode]; 34 int data[MAXN], M;//M为总结点个数 35 36 //初始化线段树 37 void build(int l, int r){ 38 for (int i = 2 * M - 1; i > 0; i--){ 39 if (i >= M){ 40 tree[i].sum = data[i - M]; 41 tree[i].l = tree[i].r = (i - M);//叶子节点 42 } 43 else { 44 tree[i].sum = tree[i<<1].sum + tree[(i<<1)+1].sum; 45 tree[i].l = tree[i<<1].l; 46 tree[i].r = tree[(i<<1)+1].r; 47 } 48 } 49 } 50 long long query(int l, int r){ 51 long long sum = 0;//sum记录和 52 int numl = 0, numr = 0; 53 l += M - 1; 54 r += M + 1; 55 while ((l ^ r) != 1){ 56 if (~l&1){//l取反,表示l是左节点 57 sum += tree[l ^ 1].sum; 58 numl += (tree[l ^ 1].r - tree[l ^ 1].l + 1); 59 } 60 if (r & 1){ 61 sum += tree[r ^ 1].sum; 62 numr += (tree[r ^ 1].r - tree[r ^ 1].l + 1); 63 } 64 l>>=1; 65 r>>=1; 66 //numl,numr使用来记录标记的 67 sum += numl * tree[l].d; 68 sum += numr * tree[r].d; 69 } 70 for (l >>= 1; l > 0; l >>= 1) sum += (numl + numr) * tree[l].d; 71 return sum; 72 } 73 74 void add(int l, int r, int val){ 75 int numl = 0, numr = 0; 76 l += M - 1; 77 r += M + 1; 78 while ((l ^ r) != 1){ 79 if (~l&1){//l取反 80 tree[l ^ 1].d += val; 81 tree[l ^ 1].sum += (tree[l ^ 1].r - tree[l ^ 1].l + 1) * val; 82 numl += (tree[l ^ 1].r - tree[l ^ 1].l + 1); 83 } 84 if (r & 1){ 85 //更新另一边 86 tree[r ^ 1].d += val; 87 tree[r ^ 1].sum += (tree[r ^ 1].r - tree[r ^ 1].l + 1) * val; 88 numr += (tree[r ^ 1].r - tree[r ^ 1].l + 1); 89 } 90 l>>=1; 91 r>>=1; 92 tree[l].sum += numl * val; 93 tree[r].sum += numr * val; 94 } 95 //不要忘了往上更新 96 for (l >>= 1; l > 0; l >>= 1) tree[l].sum += (numl+numr) * val; 97 } 98 int n, m; 99 100 void init(){ 101 scanf("%d%d", &n, &m); 102 for (int i = 1; i <= n; i++) scanf("%d", &data[i]); 103 M = 1;while (M < (n + 2)) M <<= 1;//找到最大的段 104 build(0, M - 1); 105 } 106 void work(){ 107 while (m--){ 108 char str[2]; 109 scanf("%s", str); 110 if (str[0] == ‘Q‘){ 111 int l, r; 112 scanf("%d%d", &l, &r); 113 printf("%lld\n", query(l, r)); 114 } 115 else{ 116 int val, l, r; 117 scanf("%d%d%d", &l, &r, &val); 118 if (val != 0) add(l, r, val); 119 } 120 } 121 } 122 123 int main(){ 124 125 init(); 126 work(); 127 return 0; 128 }
【POJ3468】【zkw线段树】A Simple Problem with Integers
原文:http://www.cnblogs.com/hoskey/p/4340214.html