暑期训练狂刷系列——poj 3468 A Simple Problem with Integers (线段树+区间更新)

题目连接:

  http://poj.org/problem?id=3468

题目大意:

  给出n个数,有两种操作:

    1:"C a b c",[a,b]中的每一个数都加上c。

    2:"Q a b",求[a,b]中每个数相加的和。

解题思路:

  线段树更新到每一个节点的话,由于节点数目和查询次数原因会tle,所以在每一个节点内定义一个标志变量表示当前节点的下一层为更新,每次查询时候有需要的话在更新到下一层。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 using namespace std;
  6 const int maxn = 400010;
  7 const int INF = 0x3f3f3f3f;
  8 #define LL __int64
  9 struct node
 10 {
 11     LL L, R;
 12     LL sum, add;
 13     LL Mid()
 14     {
 15         return (L + R) / 2;
 16     }
 17 };
 18 node tree[maxn];
 19 LL res;
 20
 21 void build(LL root, LL l, LL r)
 22 {
 23     tree[root].L = l;
 24     tree[root].R = r;
 25     tree[root].sum = tree[root].add = 0;
 26
 27     if (l == r)
 28         return ;
 29     build (2*root+1, l, tree[root].Mid());
 30     build (2*root+2, tree[root].Mid()+1, r);
 31 }
 32 void insert (LL root, LL s, LL e, LL x)
 33 {
 34     tree[root].sum += x * (e - s + 1);
 35     if (tree[root].L == s && e == tree[root].R)//更新到区间
 36         {
 37             tree[root].add += x;
 38             return ;
 39         }
 40     if (e <= tree[root].Mid())
 41         insert (2*root+1, s, e, x);
 42     else if (tree[root].Mid() < s)
 43         insert (2*root+2, s, e, x);
 44     else
 45     {
 46         insert (2*root+1, s, tree[root].Mid(), x);
 47         insert (2*root+2, tree[root].Mid()+1, e, x);
 48     }
 49 }
 50 void query (LL root, LL s, LL e)
 51 {
 52
 53     if (tree[root].L == s && e == tree[root].R)
 54     {
 55         res += tree[root].sum;
 56         return ;
 57     }
 58     if (tree[root].add)
 59     {//向下继续更新
 60         tree[2*root+1].add += tree[root].add;
 61         tree[2*root+2].add += tree[root].add;
 62         tree[2*root+1].sum += tree[root].add * (tree[2*root+1].R - tree[2*root+1].L + 1);
 63         tree[2*root+2].sum += tree[root].add * (tree[2*root+2].R - tree[2*root+2].L + 1);
 64         tree[root].add = 0;
 65     }
 66     if (e <= tree[root].Mid())
 67         query (2*root+1, s, e);
 68     else if (tree[root].Mid() < s)
 69         query (2*root+2, s, e);
 70     else
 71     {
 72         query (2*root+1, s, tree[root].Mid());
 73         query (2*root+2, tree[root].Mid()+1, e);
 74     }
 75 }
 76 int main ()
 77 {
 78     LL n, m, num;
 79     while (scanf ("%I64d %I64d", &n, &m) != EOF)
 80     {
 81         build (0, 1, n);
 82         for (int i=1; i<=n; i++)
 83         {
 84             scanf ("%I64d", &num);
 85             insert (0, i, i, num);
 86         }
 87         char str[2];
 88         LL s, e;
 89         while (m --)
 90         {
 91             scanf ("%s %I64d %I64d", str, &s, &e);
 92             if (str[0] == ‘Q‘)
 93             {
 94                 res = 0;
 95                 query (0, s, e);
 96                 printf ("%I64d\n", res);
 97             }
 98             else
 99             {
100                 scanf ("%I64d", &num);
101                 insert (0, s, e, num);
102             }
103         }
104     }
105     return 0;
106 }
时间: 2024-10-12 17:48:19

暑期训练狂刷系列——poj 3468 A Simple Problem with Integers (线段树+区间更新)的相关文章

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

[POJ] 3468 A Simple Problem with Integers [线段树区间更新求和]

A Simple Problem with Integers Description You have N integers, A1, A2, ... , 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

POJ 3468 A Simple Problem with Integers(线段树 区间更新)

http://poj.org/problem?id=3468 题意 :对于一个序列有两种操作 1 查询 l到r 的和 2 对于l 到r上的每个数 加上 up 思路: 用单点更新必然超时 所以需要区间更新 (位运算时 注意 m-m>>1 与 m-(m>>1) 的区别) #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using names

POJ 3468 A Simple Problem with Integers 线段树 区间更新 区间查询

题目链接: http://poj.org/problem?id=3468 题目描述: 一组数列, 可进行一段区间加上某一个数, 和区间查询 解题思路: 线段树, 之前的那道题是求总区间直接输出sum[1] 就可以了, 这次有了区间查询, 同理, 查询的时候Pushdown 代码: #include <iostream> #include <cstdio> #include <string> #include <vector> #include <map

(简单) POJ 3468 A Simple Problem with Integers , 线段树+区间更新。

Description You have N integers, A1, A2, ... , 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. 题意

POJ 3468 A Simple Problem with Integers(线段树区间更新区间求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 67511   Accepted: 20818 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj 3468 A Simple Problem with Integers 线段树区间更新

点击打开链接题目链接 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 63565   Accepted: 19546 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations.

POJ 3468 A Simple Problem with Integers (线段树区域更新)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 62431   Accepted: 19141 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj 3468 A Simple Problem with Integers 线段树第一次 + 讲解

A Simple Problem with Integers Description You have N integers, A1, A2, ... , 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