zoukankan      html  css  js  c++  java
  • POJ 3468 A Simple Problem with Integers(线段树区间求和)

    传送门: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

    题意:

    给定一个数列有n个数以及q个操作

    有两种操作:

      c:给出a,b,c 对a,b区间的数同时加上c

      q:给出a,b 求a,b区间的和

    题解:

    如果对每个节点,维护对应区间的和,可以在O(logn)时间内求出任意区间的和,但是不能够高效的实现对一个区间同时加一个值,因为需要对其所有关联节点进行更新

    为了保持线段树的高效,对于每个节点维护两个数据:

    a 给这个节点对应的区间内同时加上一个值

    b在这个节点对应的区间内除去a之外其他值的和

    代码:

    #include <stdio.h>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <deque>
    #include <iomanip>
    #include <iostream>
    #include <list>
    #include <map>
    #include <queue>
    #include <set>
    #include <utility>
    #include <vector>
    #define mem(arr, num) memset(arr, 0, sizeof(arr))
    #define _for(i, a, b) for (int i = a; i <= b; i++)
    #define __for(i, a, b) for (int i = a; i >= b; i--)
    #define IO                     
      ios::sync_with_stdio(false); 
      cin.tie(0);                 
      cout.tie(0);
    using namespace std;
    typedef long long ll;
    const ll inf = 0x3f3f3f3f;
    const double EPS = 1e-10;
    const ll mod = 1000000007LL;
    const int N = 1 << 19;
    ll data[N],datb[N];
    int n,q;
    void build(int l, int r, int k) {
      data[k] = datb[k] = 0;
      if(l==r) {
        scanf("%d",&datb[k]);return ;
      }
      build(l,(l+r)/2,k<<1);
      build((l+r)/2+1,r,k<<1|1);
      datb[k] = datb[k<<1] + datb[k<<1|1];
    }
    void update(int a,int b,int k,int l,int r,int dat) {
      if(a <= l && b >= r) {
          data[k] += dat;
      } else if(a <= r && b >= l) {
          datb[k] += (min(b,r) - max(a,l) + 1) * x;
          update(a,b,k<<1,l,(l+r)/2,dat);
          update(a,b,k<<1|1,(l+r)/2+1,r,dat);
      }
    }
    ll query(int a,int b,int k,int l,int r) {
        if(b < l || a > r) return 0;
        else if(a <= l && b >= r) return data[k] * (r-l+1) + datb[k];
        else {
            ll res = (min(b,r) - max(a,l) + 1) *data[k];
            res += query(a,b,k<<1,l,(l+r)/2);
            res += query(a,b,k<<1|1,(l+r)/2+1);
            return res;
        }
    }
    int main() {
      scanf("%d%d",&n,&q);
      build(1,n,1);
      char op;
      int a,b,c;
      _for(i, 1, q) {
          getchar();
          scanf("%c",&op);
          if(op == 'Q') {
              scanf("%d%d",&a,&b);
              printf("%lld
    ",query(a,b,1,1,n));
          } else {
              scanf("%d%d%d",&a,&b,&c);
              update(a,b,1,1,n,c);
          }
      }
      return 0;
    }
    宝剑锋从磨砺出 梅花香自苦寒来
  • 相关阅读:
    文件上传跨域解决方案-jQuery-File-Upload
    求数列的的增幅,已知起始列和结束列,中间阶梯数
    mud那些坑 find_object问题
    jquery mCustomScrollbar使用
    JS的Date对象
    JS获取当前日期
    Go数组求和
    Go九九乘法表
    Go语言基础之time包
    Go语言基础之流程控制
  • 原文地址:https://www.cnblogs.com/GHzcx/p/8920155.html
Copyright © 2011-2022 走看看