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.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b” means querying the sum of Aa, Aa+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
题意:
输入N、Q,代表整数的个数和操作的个数
然后输入N个整数,Q个操作
有两种操作:
“C a b c”表示第a-b个数分别加上c
“Q a b”表示输出第a-b个数的和
输出每个Q操作的结果
思路:
线段树+lazy(思想)
只用线段树会TLE。。。
注意范围,用long long 定义数组(不然WA)
//用update函数更新时,当结点idx表示的范围与查询范围恰好相同时,本来应该更新idx子结点的值,而Lazy思想暂时不更新子结点的值,到此就return,等下次需要用到idx子结点的值的时候再更新,从而节省时间
#include <iostream>
#include <cstdio>
#include <cstring>
#include <sstream>
using namespace std;
const int Maxn=100005;
int num[Maxn];
long long Tree[Maxn*4],add[Maxn*4];//Tree[]储存每个结点的值,add[]用来存储每个结点应该加的值,注意范围是long long(因为没考虑到范围一直WA...)
/*struct node
{
int l,r;
int mid()
return (l+r)>>2;
}N[Maxn*4];*/
void build(int l,int r,int idx)//构造树
{
add[idx]=0;//初始化为0
if(l==r)//叶子结点
{
Tree[idx]=num[l];
}
else
{
int mid=(l+r)>>1;
build(l,mid,idx<<1);
build(mid+1,r,idx<<1|1);
Tree[idx]=Tree[idx<<1]+Tree[idx<<1|1];//pushUp,通过当前结点idx把向上递归到更新根结点的值,即各个子结点值的和
}
}
void pushDown(int index,int m)//通过当前结点index向下递归更新index子结点的值,lazy思想核心代码
{
if(add[index])//add[]不为0,说明当前结点的子结点值还未更新
{
add[index<<1]+=add[index];//更新左右儿子的add[]值
add[index<<1|1]+=add[index];
Tree[index<<1]+=add[index] * (m - (m>>1));//更新左右儿子的结点值
Tree[index<<1|1]+=add[index]*(m>>1);
add[index]=0;//重新置为0
}
}
long long query(int l,int r,int index,int left,int right)//求给定区间内根结点值的和
{
if(l==left&&r==right)//若当前区间与查询区间相同,返回结点值
return Tree[index];
pushDown(index,r-l + 1);//更新子结点的值
int mid=(l+r)>>1;
if(right<=mid)
return query(l,mid,index<<1,left,right);
else if(left>mid)
return query(mid+1,r,index<<1|1,left,right);
else
return query(l,mid,index<<1,left,mid)+query(mid+1,r,index<<1|1,mid+1,right);
}
void update(int l,int r,int index,int left,int right,int c)//更新给定区间内的结点值
{
if(l==left&&r==right)//当前结点表示区间与给定区间相同
{
add[index]+=c;//更新结点的add值
Tree[index]+=(r-l+1)*c;//更新结点值
return;//返回,暂不更新子结点的值,待之后要用到时再通过pushUp()更新,lazy思想
}
if(l==r)//叶子结点
return;
pushDown(index,r-l+1);//更新子结点
int mid=(l+r)>>1;
if(right<=mid)
update(l,mid,index<<1,left,right,c);
else if(left>mid)
update(mid+1,r,index<<1|1,left,right,c);
else
{
update(l,mid,index<<1,left,mid,c);
update(mid+1,r,index<<1|1,mid+1,right,c);
}
Tree[index]=Tree[index<<1]+Tree[index<<1|1];//pushUp
}
int main()
{
int N,Q,l,r,c;
long long sum;
char ch;
string str;
stringstream ss;
cin>>N>>Q;
for(int i=1;i<=N;i++)
{
scanf("%d",&num[i]);
}
build(1,N,1);
/*for(int i=0;i<Q;i++)
{
getline(cin,str);
ss<<str;
if(str[0]=='Q')
{
ss>>ch>>l>>r;
ss.clear();
//cout<<l<<r<<endl;
sum=query(1,N,1,l,r);
cout<<sum<<endl;
}
else if(str[0]=='C')
{
ss>>ch>>l>>r>>c;
ss.clear();
update(1,N,1,l,r,c);
}
}*/
while(Q--)
{
getchar();
scanf("%c",&ch);
if(ch=='C')
{
scanf("%d%d%d",&l,&r,&c);
update(1,N,1,l,r,c);
}
if(ch=='Q')
{
scanf("%d%d",&l,&r);
sum=query(1,N,1,l,r);
cout<<sum<<endl;
}
}
return 0;
}