• 【POJ3468】【树状数组区间修改】A Simple Problem with Integers


    Description

    You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of AaAa+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

    The sums may exceed the range of 32-bit integers.

    Source

    【分析】

    以前一直以为树状数组只能单点修改,区间询问,今天算是见识到了树状数组的区间修改了。

    不说多的了,很巧妙的感觉,对于一个修改操作(a,b,c),将[a,b]区间整体加上一个c

    可以把它拆开成两个部分(a,n,c),和(b + 1,n,-c),这个时候就好做了,用两个树状数组。

    一个树状数组记录从修改点开始一直到结束所增加的所有量,及c*(n-a+1)。另一个记录下增量值c。

    那么对于一个在a点右边而在b点左边的点x,它所得到的增量为c*(n-a+1) - c*(n-x)。很好维护了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <vector>
     6 #include <utility>
     7 #include <iomanip>
     8 #include <string>
     9 #include <cmath>
    10 #include <map>
    11 
    12 const int MAXN = 100000 + 10; 
    13 const int MAX = 32000 + 10; 
    14 using namespace std;
    15 typedef long long ll;
    16 int n, m;
    17 ll sum[MAXN];//记录原始序列
    18 ll C[2][MAXN]; 
    19 
    20 int lowbit(int x){return x&-x;}
    21 ll get(int k, int x){
    22     ll cnt = 0;
    23     while (x > 0){
    24           cnt += C[k][x];
    25           x -= lowbit(x);
    26     }
    27     return cnt;
    28 }
    29 void add(int k, int x, ll val){
    30      while (x <= n){
    31            C[k][x] += val;
    32            x += lowbit(x); 
    33      }
    34      return ;
    35 }
    36 void work(){
    37      memset(C, 0, sizeof(C));//0记录总值、1录增量 
    38      sum[0] = 0;
    39      scanf("%d%d", &n, &m);
    40      for (int i = 1; i <= n; i++){
    41          scanf("%lld", &sum[i]);
    42          sum[i] += sum[i - 1];
    43      }
    44      for (int i = 1; i <= m; i++){
    45          char str[2];
    46          scanf("%s", str);
    47          if (str[0] == 'Q'){
    48             int l, r;
    49             scanf("%d%d", &l, &r);
    50             printf("%lld
    ", sum[r] - sum[l - 1] +(get(0, r) - get(1, r) * (n - r)) - (get(0, l - 1) - get(1, l - 1) * (n - l + 1)));
    51          }else{
    52                int l, r;
    53                ll x;
    54                scanf("%d%d%lld", &l, &r, &x);
    55                add(0, l, (n - l + 1) * x);
    56                add(0, r + 1, (n - r) * (-x));
    57                add(1, l, x);
    58                add(1, r + 1, -x); 
    59          }
    60      }
    61      //printf("
    %d
    ", get(0, 10));
    62 }
    63 
    64 int main(){
    65     int T;
    66     #ifdef LOCAL
    67     freopen("data.txt",  "r",  stdin);
    68     freopen("out.txt",  "w",  stdout); 
    69     #endif
    70     work();
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    0302思考并回答一些问题
    0104 自下而上
    1203 有穷自动机的构造
    11 10我的评论
    1029 C语言文法翻译(2)
    1014 对编译程序的心得与总结
    我们小组的编译程序
    0921 词法分析程序
    0909 关于编译原理的思考
    数据库设计之数据库设计三大范式
  • 原文地址:https://www.cnblogs.com/hoskey/p/4320386.html
Copyright © 2020-2023  润新知