POJ 3468 A Simple Problem with Integers

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.

 

赤裸裸的线段树

之前看了一点,因为期末考搁了一个月,于是现在就只记得大致思路了。

重写时各种纠结,各种RE、各种WA。

View Code
  1 #include <cstdio>
  2 
  3 const int N = 100010;
  4 struct Node
  5 {
  6     int left, right;
  7     long long sum, add;
  8 } node[N * 6];
  9 int num[N];
 10 
 11 void CreateTree(int L, int R, int id)
 12 {
 13     node[id].left = L;
 14     node[id].right = R;
 15     node[id].add = 0;
 16     if (L == R)
 17     {
 18         node[id].sum = num[L];
 19         return;
 20     }
 21     int mid = (L + R) / 2;
 22     CreateTree(L, mid, 2 * id);
 23     CreateTree(mid + 1, R, 2 * id + 1);
 24     node[id].sum = node[2 * id].sum + node[2 * id + 1].sum;
 25 }
 26 
 27 void Update(int L, int R, int val, int id)
 28 {
 29     if (node[id].left == L && node[id].right == R)
 30     {
 31         node[id].add += val;
 32         return;
 33     }
 34     //由于更新区间总是被线段树上的区间完全覆盖
 35     //所以这里有R-L <= node[id].right-node[id].left
 36     node[id].sum += (R - L + 1) * val;
 37     int mid = (node[id].left + node[id].right) / 2;
 38     if (R <= mid)
 39     {
 40         Update(L, R, val, 2 * id); //搜索左子树
 41     }
 42     else
 43     {
 44         if (L > mid)
 45         {
 46             Update(L, R, val, 2 * id + 1); //搜索右子树
 47         }
 48         else
 49         {
 50             Update(L, mid, val, 2 * id);
 51             Update(mid + 1, R, val, 2 * id + 1);
 52         }
 53     }
 54 }
 55 
 56 long long Find(int L, int R, int id)
 57 {
 58     //如果检测到当前区间有增量,则加到当前区间的和上
 59     //同样该区间的所有子区间都应该有相同的增量,通过维护子区间的add实现
 60     if (node[id].add != 0)
 61     {
 62         node[id].sum += (node[id].right - node[id].left + 1) * node[id].add;
 63         node[2 * id].add += node[id].add;
 64         node[2 * id + 1].add += node[id].add;
 65         node[id].add = 0;
 66     }
 67     if (node[id].left == L && node[id].right == R)
 68     {
 69         return node[id].sum;
 70     }
 71     long long sum = 0;
 72     int mid = (node[id].left + node[id].right) / 2;
 73     if (R <= mid)
 74     {
 75         sum += Find(L, R, 2 * id);
 76     }
 77     else
 78     {
 79         if (L > mid)
 80         {
 81             sum += Find(L, R, 2 * id + 1);
 82         }
 83         else
 84         {
 85             sum += Find(L, mid, 2 * id) + Find(mid + 1, R, 2 * id + 1);
 86         }
 87     }
 88     return sum;
 89 }
 90 
 91 int main()
 92 {
 93     int n, q;
 94     scanf("%d%d", &n, &q);
 95     for (int i = 1; i <= n; i++)
 96         scanf("%d", &num[i]);
 97     CreateTree(1, n, 1);
 98     while (q--)
 99     {
100         int a, b, w;
101         char opt;
102         scanf("\n%c", &opt);
103         if (opt == 'C')
104         {
105             scanf("%d%d%d", &a, &b, &w);
106             Update(a, b, w, 1);
107         }
108         else
109         {
110             scanf("%d%d", &a, &b);
111             printf("%I64d\n", Find(a, b, 1));
112         }
113     }
114     return 0;
115 }

 

posted @ 2012-06-30 21:36  dgsrz  阅读(136)  评论(0编辑  收藏  举报