POJ 3468 A Simple Problem with Integers 线段树
线段树
View Code
1 /* 2 poj3468 3 */ 4 #include <iostream> 5 using namespace std; 6 const int N = 100005; 7 8 struct node 9 { 10 int left, right; 11 long long num, add; 12 }tree[4*N]; 13 14 int L(int n) 15 { 16 return n<<1; 17 } 18 int R (int n) 19 { 20 return (n<<1) | 1; 21 } 22 void update(int step) //若当前节点的标志位add有值,则更新其左右节点 23 { 24 tree[L(step)].num += tree[step].add * (tree[L(step)].right - tree[L(step)].left + 1); 25 tree[L(step)].add += tree[step].add; //将标志位传给子节点 26 tree[R(step)].num += tree[step].add * (tree[R(step)].right - tree[R(step)].left + 1); 27 tree[R(step)].add += tree[step].add; 28 tree[step].add = 0; //父节点清0 29 } 30 int a[N]; 31 32 void build(int l, int r, int step) 33 { 34 tree[step].left = l; 35 tree[step].right = r; 36 tree[step].add = 0; 37 if (l == r) //到达叶子节点了 38 { 39 tree[step].num = a[l]; 40 return; 41 } 42 int mid = (l + r) >> 1; 43 build(l, mid, L(step)); 44 build(mid+1, r, R(step)); 45 //其构造是自下而上(先求出其子节点的值),那么其父亲节点很明显就是其左右节点值的和 46 tree[step].num = tree[L(step)].num + tree[R(step)].num; 47 } 48 49 void insert(int l, int r, int step, int add) 50 { 51 if (l<= tree[step].left && tree[step].right <= r) 52 { 53 tree[step].add += add; 54 tree[step].num += add * (tree[step].right - tree[step].left + 1); //add * len 55 return; 56 } 57 if (tree[step].add != 0) // 58 { 59 update(step); 60 } 61 int mid = (tree[step].left + tree[step].right) >> 1; 62 if (mid >= l) 63 insert(l, r, L(step), add); 64 if (mid < r) 65 insert(l, r, R(step), add); 66 //由于可能其子节点有更新,我们需要在重新计算一次step这层的值 67 tree[step].num = tree[L(step)].num + tree[R(step)].num; 68 } 69 70 long long query(int l, int r, int step) 71 { 72 long long ans = 0; 73 if (l <= tree[step].left && tree[step].right <= r) 74 { 75 return tree[step].num; 76 } 77 if (tree[step].add != 0) 78 { 79 update(step); 80 } 81 int mid = (tree[step].left + tree[step].right) >> 1; 82 if (mid >= l) //与左节点有交集 83 ans += query(l, r, L(step)); 84 if (mid < r) //与右节点有交集 85 ans += query(l, r, R(step)); 86 return ans; 87 } 88 89 int main() 90 { 91 int n, q, i, k, l, r, add; 92 char str; 93 94 scanf("%d%d", &n, &q); 95 for (i=1; i<=n; i++) 96 scanf("%d", &a[i]); 97 build(1, n, 1); 98 99 while (q--) 100 { 101 getchar(); 102 scanf("%c", &str); 103 // printf("----->%c\n",str); 104 if (str == 'Q') 105 { 106 scanf("%d%d", &l, &r); 107 printf("%lld\n", query(l, r, 1)); 108 } 109 else 110 { 111 scanf("%d%d%d", &l, &r, &add); 112 insert(l, r, 1, add); 113 } 114 115 } 116 117 return 0; 118 }