zoukankan      html  css  js  c++  java
  • POJ3468 A Simple Problem with Integers(线段树延时标记)

    题目地址http://poj.org/problem?id=3468

    题目大意很简单,有两个操作,一个

    Q a, b 查询区间[a, b]的和

    C a, b, c让区间[a, b] 的每一个数+c

    第一次线段树的延时标记,花了好大的功夫才写好==!

    很容易看出来使用使用线段树记录区间的和,但是难点在于每次修改的是一个区间而不是一个点

    所以采用的方法就是每次做修改操作时,只将区间[a,b]的标记+c,而不是真正意义上的将区间[a, b] 的每一个值+c。

    而当我们做查询操作时,就只需要将区间[a, b]在从[1, N]开始查找到查找到时所经过的区间的标记往下传递就可以了(同时记得更新当前节点的值)

     1 #include <map>
     2 #include <set>
     3 #include <stack>
     4 #include <queue>
     5 #include <cmath>
     6 #include <ctime>
     7 #include <vector>
     8 #include <cstdio>
     9 #include <cctype>
    10 #include <cstring>
    11 #include <cstdlib>
    12 #include <iostream>
    13 #include <algorithm>
    14 using namespace std;
    15 #define INF 0x3f3f3f3f
    16 #define mem0(a) memset(a,0,sizeof(a))
    17 #define mem1(a) memset(a,-1,sizeof(a))
    18 #define lson k<<1, L, mid
    19 #define rson k<<1|1, mid+1, R
    20 
    21 typedef long long LL;
    22 const double eps = 1e-12;
    23 const int MAXN = 100005;
    24 const int MAXM = 500005;
    25 
    26 struct Node { LL sum, add; } tree[MAXN<<2];
    27 int a, b, N, Q;
    28 LL c;
    29 
    30 void updataChild(int k, int L, int R)//将编号为k的标记传到他的子节点去
    31 {
    32     tree[k].sum += (R-L+1) * tree[k].add;//先更新它自己的sum值
    33     tree[k<<1].add += tree[k].add;//将左右子节点的add值更新
    34     tree[k<<1|1].add += tree[k].add;
    35     tree[k].add = 0;//去掉标记
    36 }
    37 
    38 void update(int k, int L, int R)//更新区间的值
    39 {
    40     if(R<a || b<L) return ;//不再区间内
    41 
    42     if(a<=L && R<=b) { tree[k].add += c;  return; }//实际上只更新这个区间的add值
    43 
    44     int mid = (L+R)>>1;     update(lson);      update(rson); //往左和往右更新
    45 
    46     tree[k].sum = tree[k<<1].sum + tree[(k<<1)+1].sum//更新当前节点的sum
    47                   + (mid-L+1)*tree[k<<1].add + (R-mid)*tree[k<<1|1].add;
    48 }
    49 
    50 LL query(int k, int L, int R)
    51 {
    52     if(R<a || b<L) return 0;
    53 
    54     if(a<=L && R<=b) return tree[k].sum + (R-L+1)*tree[k].add;//注意加上当前节点的标记
    55 
    56     int mid = (L+R)>>1;  updataChild(k, L, R);//吧标记传到子节点
    57 
    58     return query(lson) + query(rson);
    59 }
    60 
    61 int main()
    62 {
    63     while(~scanf("%d %d", &N, &Q))
    64     {
    65         mem0(tree); char ch;
    66         for(a=1;a<=N;a++)
    67         {
    68             scanf("%lld%*c", &c);  b = a;//区间是[a, a]
    69             update(1, 1, N);
    70         }
    71         for(int i=0;i<Q;i++)
    72         {
    73             scanf("%c", &ch);
    74             if(ch == 'Q')
    75             {
    76                 scanf("%d %d%*c", &a, &b);
    77                 printf("%lld
    ", query(1,1,N));
    78             }
    79             else
    80             {
    81                 scanf("%d %d %lld%*c", &a, &b, &c);
    82                 update(1,1,N);
    83             }
    84         }
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    SpringBoot 官方文档中文版
    SpringBoot 官方文档中文版
    SpringBoot 官方文档中文版
    RK 打包脚本 make_ext4fs system.img
    Linux安装docker-compose
    Linux使用docker安装Jenkins 并进行jar包发布
    JAVA把InputStream 转 字节数组(byte[])
    SpringBoot简单整合分布式任务调度平台(XXL-JOB)
    SpringBoot项目bootstrap.yml配置文件不加载
    JAVA中Base64和byte数组(byte[]) 相互转换
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/3574008.html
Copyright © 2011-2022 走看看