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.
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
Hint
Source
#include<cstdio>
using namespace std;
typedef long long LL; ///因为a的初始范围是±1e9,为了避免后续操作导致a超范围,所以这里直接上longlong
int a[100005];
struct trees{
int left,right,mid;
LL sum,mark; ///记录该父节点或者子叶节点的值和是否进行了操作
}tree[1000050];
void build(int x,int y,int num){ ///建树
tree[num].left=x;
tree[num].right=y;
tree[num].mid=(x+y)>>1;
tree[num].mark=0; ///mark==0表示当前节点并未被操作
if(x==y){
tree[num].sum=a[x];
return ;
}
int mid=(x+y)>>1;
build(x,mid,num<<1);
build(mid+1,y,(num<<1)+1);
tree[num].sum=(tree[num<<1].sum+tree[(num<<1)+1].sum);
}
LL query(int x,int y,int num){ ///区间查询,返回x~y区间的和
if(tree[num].left==x&&tree[num].right==y){
return tree[num].sum+tree[num].mark*(LL)(y-x+1);
} ///当刚好是x~y这个区间时,mark继续可以不用变动
if(tree[num].mark!=0){ ///当mark不为0时,对该节点的子节点的mark值进行操作,使之加上当前节点的mark值
tree[num<<1].mark+=tree[num].mark;
tree[(num<<1)+1].mark+=tree[num].mark;
tree[num].sum+=(LL)(tree[num].right-tree[num].left+1)*tree[num].mark;
tree[num].mark=0; ///当前节点的mark清零
}
if(tree[num].mid>=y){
return query(x,y,num<<1);
}
else if(tree[num].mid<x){
return query(x,y,(num<<1)+1);
}
else {
return query(x,tree[num].mid,num<<1)+query(tree[num].mid+1,y,(num<<1)+1);
}
}
void update(int x,int y,int val,int num){ ///x~y区间修改
if(tree[num].left==x&&tree[num].right==y){ ///当刚好是该区间时,将该节点的mark值赋值为val,并跳出
tree[num].mark+=val;
return ;
}
tree[num].sum+=(LL)val*(y-x+1); ///如果该节点的区间大于说需要查找的区间,直接将该节点的sum进行加
if(tree[num].mid>=y){
update(x,y,val,num<<1);
}
else if(tree[num].mid<x){
update(x,y,val,(num<<1)+1);
}
else{
update(x,tree[num].mid,val,num<<1);
update(tree[num].mid+1,y,val,(num<<1)+1);
}
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
int i;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,n,1);
int x,y,key;
while(m--){
char str[105];
scanf("%s",&str);
if(str[0]=='Q'){
scanf("%d%d",&x,&y);
printf("%lld\n",query(x,y,1));
}
else if(str[0]=='C'){
scanf("%d%d%d",&x,&y,&key);
update(x,y,key,1);
}
}
}
return 0;
}