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了好久.......












 posted on 2016-07-13 18:56  qzgxlx  阅读(207)  评论(0编辑  收藏  举报