zoukankan      html  css  js  c++  java
  • 【POJ】3468 A Simple Problem with Integers ——线段树 成段更新 懒惰标记 Prime

     A Simple Problem with Integers
    Time Limit:5000MS   Memory Limit:131072K
    Case Time Limit:2000MS

    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.
     
    题解:本题也是线段树系列的模板题之一,要求的是成段更新+懒惰标记。PS:原题的说明有问题,上面说的“C a b c”中的c的范围其实在int32之外,需要使用long long,否则定是WA,真心坑爹,连WA多次,还是在discuss中看到的原因。
     
    稍微讲解下代码中的一些细节: step<<1 与 step<<1|1,意思分别是step*2 和step*+1,具体为什么,可以回去复习一下位运算
     
    AC代码如下:
     
     
      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 typedef long long ll;
      5 const int LEN = 100000 * 4;
      6 
      7 struct line
      8 {
      9     int left;
     10     int right;
     11     ll value;
     12     ll lazy;  //懒惰标记
     13 }line[LEN];
     14 
     15 void buildt(int l, int r, int step)  //建树初始化
     16 {
     17     line[step].left = l;
     18     line[step].right = r;
     19     line[step].lazy = 0;
     20     line[step].value = 0;
     21     if (l == r)
     22         return;
     23     int mid = (l + r) / 2;
     24     buildt(l, mid, step<<1);
     25     buildt(mid+1, r, step<<1|1);
     26 }
     27 
     28 void pushdown(int step)
     29 {
     30     if (line[step].left == line[step].right) //如果更新到最深处的子节点,返回
     31         return;
     32     if (line[step].lazy != 0){  //如果有懒惰标记,向下传递懒惰标记且更新两个子节点的值
     33         line[step<<1].lazy += line[step].lazy;
     34         line[step<<1|1].lazy += line[step].lazy;
     35         line[step<<1].value += (line[step<<1].right - line[step<<1].left + 1) * line[step].lazy;
     36         line[step<<1|1].value += (line[step<<1|1].right - line[step<<1|1].left + 1) * line[step].lazy;
     37         line[step].lazy = 0;
     38     }
     39 }
     40 
     41 void update(int l, int r, ll v, int step)
     42 {
     43     line[step].value += v * (r-l+1);  //更新到当前节点,就在当前节点的value中加上增加的值
     44     pushdown(step);
     45     if (line[step].left == l && line[step].right == r){ //如果到达目标线段,做上懒惰标记,返回
     46         line[step].lazy = v;
     47         return;
     48     }
     49     int mid = (line[step].left + line[step].right) / 2;
     50     if (r <= mid)
     51         update(l, r, v, step<<1);
     52     else if (l > mid)
     53         update(l, r, v, step<<1|1);
     54     else{
     55         update(l, mid, v, step<<1);
     56         update(mid+1, r, v, step<<1|1);
     57     }
     58 }
     59 
     60 ll findans(int l, int r, int step)
     61 {
     62     if (l == line[step].left && r == line[step].right)  //如果找到目标线段,返回值
     63         return line[step].value;
     64     pushdown(step);
     65     int mid = (line[step].left + line[step].right) / 2;
     66     if (r <= mid)
     67         return findans(l, r, step<<1);
     68     else if (l > mid)
     69         return findans(l, r, step<<1|1);
     70     else
     71         return findans(l, mid, step<<1) + findans(mid+1, r, step<<1|1);
     72 }
     73 
     74 int main()
     75 {
     76     //freopen("in.txt", "r", stdin);
     77     int n, q;
     78     scanf("%d %d", &n, &q);
     79     buildt(1, n, 1);
     80     for(int i = 1; i <= n; i++){
     81         ll t;
     82         scanf("%I64d", &t);
     83         update(i, i, t, 1);
     84     }
     85     for(int i = 0; i < q; i++){
     86         char query[2];
     87         scanf("%s", query);
     88         if (query[0] == 'C'){
     89             int a, b;
     90             ll c;
     91             scanf("%d %d %I64d", &a, &b, &c);
     92             update(a, b, c, 1);
     93         }
     94         else if (query[0] == 'Q'){
     95             int a, b;
     96             scanf("%d %d", &a, &b);
     97             printf("%I64d\n", findans(a, b, 1));
     98         }
     99     }
    100     return 0;
    101 }
  • 相关阅读:
    Java知识体系之基础知识
    002-JavaNIO
    001-四种常见的IO模型
    c/c++面试题(6)运算符重载详解
    c/c++面试题(5)(c++重要的概念详解)
    c/c++面试题(4)字符串翻转/打印任意进制格式/类型转换
    c/c++面试题(3)strcat/strcmp/strlen/strcpy的实现
    c/c++面试题(2)
    c/c++面试题(1)
    cocos2dx 3.0 之 lua 创建类 (二)
  • 原文地址:https://www.cnblogs.com/kevince/p/3888608.html
Copyright © 2011-2022 走看看