poj-3468-A Simple Problem with Integers-线段树入门+区间更新

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

Hint

The sums may exceed the range of 32-bit integers.
 
题意:
  C:对区间[l,r]每一个数+c; Q:查询区间[l,r]的所有元素的总和。
 
  1 #include<iostream>
  2 #include<string.h>
  3 #include<cmath>
  4 #include<stdio.h>
  5 #include<algorithm>
  6 #include<stdlib.h>
  7 #include<iomanip>
  8 #define inf 0x3f3f3f3f
  9 #define ios() std::ios::sync_with_stdio(false)
 10 #define cin() cin.tie(0)
 11 #define cout() cout.tie(0)
 12 #define mem1(a) memset(a,0,sizeof(a))
 13 #define mem2(b) memset(b,'\0',sizeof(b))
 14 typedef long long ll;
 15 using namespace std;
 16 
 17 ll sum[400020],lazy[400020];//需要开到节点的四倍大小
 18 
 19 void build(int left,int right,int point)
 20 {
 21     if(left==right)
 22     {
 23         cin>>sum[point];
 24         return;
 25     }
 26     int mid=(left+right)>>1;
 27     build(left,mid,point<<1);
 28     build(mid+1,right,point<<1|1);
 29     sum[point]=sum[point<<1]+sum[point<<1|1];
 30 }
 31 
 32 void pushdown(int point,int len)
 33 {
 34     if(lazy[point])
 35     {
 36         lazy[point<<1]+=lazy[point];
 37         lazy[point<<1|1]+=lazy[point];
 38         sum[point<<1]+=lazy[point]*(len-(len>>1));
 39         sum[point<<1|1]+=lazy[point]*(len>>1);
 40         lazy[point]=0;
 41     }
 42 }
 43 
 44 void update(int x,int y,int left,int right,int point,int pluss)
 45 {
 46     if(left>=x&&right<=y)
 47     {
 48         sum[point]+=pluss*(right-left+1);
 49         lazy[point]+=pluss;
 50         return;
 51     }
 52     pushdown(point,right-left+1);
 53     int mid=(left+right)>>1;
 54     if(x<=mid)
 55         update(x,y,left,mid,point<<1,pluss);
 56     if(y>mid)
 57         update(x,y,mid+1,right,point<<1|1,pluss);
 58     sum[point]=sum[point<<1]+sum[point<<1|1];
 59 }
 60 
 61 ll query(int x,int y,int left,int right,int point)
 62 {
 63     if(left>=x&&right<=y)
 64         return sum[point];//在区间外
 65     pushdown(point,right-left+1);
 66     int mid=(left+right)>>1;
 67     ll sum1=0;
 68     if(x<=mid)
 69         sum1+=query(x,y,left,mid,point<<1);
 70     if(y>mid)
 71         sum1+=query(x,y,mid+1,right,point<<1|1);
 72     return sum1;
 73 }
 74 
 75 int main()
 76 {
 77     int n,m;
 78     while(cin>>n>>m)
 79     {
 80         mem1(sum);
 81         mem1(lazy);
 82         build(1,n,1);//开始建树,传入树的总区间,和树的根节点
 83         while(m--)
 84         {
 85             string ss;
 86             int left,r,pluss;
 87             cin>>ss;
 88             if(ss[0]=='Q')//询问区间内的和
 89             {
 90                 cin>>left>>r;
 91                 cout<<query(left,r,1,n,1)<<endl;
 92             }
 93             else if(ss[0]=='C')//往区间内每一个数上都插入pluss
 94             {
 95                 cin>>left>>r>>pluss;
 96                 update(left,r,1,n,1,pluss);
 97             }
 98         }
 99     }
100     return 0;
101 }

 

转载于:https://www.cnblogs.com/OFSHK/p/11285667.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值