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 }
  • 相关阅读:
    《Django By Example》第十二章(终章) 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十一章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第九章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第八章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
    我的superui开源后台bootstrap开发框架
    LayoutInflater 总结
    Android屏幕分辨率概念(dp、dip、dpi、sp、px)
    android studio安装问题
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/3574008.html
Copyright © 2011-2022 走看看