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

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

报告题目大意: 一串数,“C a b c" 表示在区间[a,b]中每个数 + c              "Q a b"表示查询区间[a,b] 的和

线段树:   学习了线段树后的第一道题。这道题包含了线段树的Pushdown,Pushup,Query,Build,Update几个函数,很好地让初学者了解了线段树的用法和精髓--延迟更新,即每次更新时只是做一个标记,当要查找时才继续向下更新。还要注意的是,有些题不需要向下回溯(pushup),也不需要延迟更新(pushdown),甚至连更新都不用。但是需要根据题意改变要查找的内容和更新的内容,有的需要找最大值,有的需要找和,等等,需要随机应变。线段树能解决的问题,树状数组不一定能解决,但是树状数组能解决的,线段树一定能解决。

思路:  便不多说。上代码。
  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cstdio>
  5 #define L(u) (u<<1)
  6 #define R(u) (u<<1|1)//没有分号
  7 using namespace std;
  8 int n,q;
  9 long long c;
 10 long long a[100005];
 11 struct node{
 12     int l,r;
 13     long long add,sum;
 14 };
 15 char s[2];
 16 node pp[400005];/**数据范围**/
 17 void pushup(int u)
 18 {
 19     pp[u].sum=pp[L(u)].sum+pp[R(u)].sum;
 20     return ;
 21 }
 22 void pushdown(int u)
 23 {
 24     pp[L(u)].add+=pp[u].add;
 25     pp[L(u)].sum+=(pp[L(u)].r-pp[L(u)].l+1)*pp[u].add;
 26     pp[R(u)].add+=pp[u].add;
 27     pp[R(u)].sum+=(pp[R(u)].r-pp[R(u)].l+1)*pp[u].add;
 28     pp[u].add=0;/*!!!*/
 29 }
 30 void update(int u,int left,int right,long long t)
 31 {
 32     if (left<=pp[u].l&&pp[u].r<=right)
 33     {
 34         pp[u].add+=t;
 35         pp[u].sum+=(pp[u].r-pp[u].l+1)*t;
 36         return ;
 37     }
 38     pp[u].sum+=(right-left+1)*t;
 39     if (pp[u].add) pushdown(u);
 40     int mid=(pp[u].l+pp[u].r)>>1;
 41     if (right<=mid) update(L(u),left,right,t);
 42     else /***/if (left>mid) update(R(u),left,right,t);
 43     else
 44     {
 45         update(L(u),left,mid,t);
 46         update(R(u),mid+1,right,t);
 47     }
 48     //pushup(u);
 49 }
 50
 51 void build(int u,int left,int right)
 52 {
 53     pp[u].l=left;
 54     pp[u].r=right;
 55     pp[u].add=0;
 56     if (pp[u].l==pp[u].r)
 57     {
 58         pp[u].sum=a[left];//*****
 59         return ;
 60     }
 61     int mid=(pp[u].l+pp[u].r)>>1;
 62     build(L(u),left,mid);
 63     build(R(u),mid+1,right);
 64     pushup(u);
 65 }
 66 long long query(int u,int left,int right)
 67 {
 68     if (left==pp[u].l&&pp[u].r==right)
 69         return pp[u].sum;
 70     if (pp[u].add) pushdown(u);
 71     int mid=(pp[u].l+pp[u].r)>>1;
 72     if (right<=mid) return query(L(u),left,right);
 73     if (left>mid) return query(R(u),left,right);
 74     else
 75       return (query(L(u),left,mid)+query(R(u),mid+1,right));
 76 }
 77 int main()
 78 {
 79     //freopen("tree.in","r",stdin);
 80     cin>>n>>q;
 81     for (int i=1;i<=n;i++)
 82           scanf("%lld",&a[i]);//long long 读数
 83     build(1,1,n);
 84     for (int i=1;i<=q;i++)
 85     {
 86         scanf("%s",s);
 87         if (s[0]==‘Q‘)
 88         {
 89             int k,b;
 90             scanf("%d%d",&k,&b);
 91             cout<<query(1,k,b)<<endl;
 92         }
 93         else
 94         {
 95             int k,b;
 96             cin>>k>>b>>c;
 97             update(1,k,b,c);
 98         }
 99     }
100
101     return 0;
102 }
注意事项:1、数据范围:线段树一般定义4*n            2、#difine 的使用  function() ( ** ) 注意括号没有分号;     3、runtime error :运行错误 long long a[i], %lld(linux) %I64d (windows)     4、模板答题

顺便抱怨一下,poj的评测系统太慢了,waiting了好久.......
时间: 2024-12-27 23:58:38

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 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

POJ 3468 A Simple Problem with Integers //线段树的成段更新

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59046   Accepted: 17974 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

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 线段树 区间更新 区间查询

题目链接: 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. 题意