你有N个整数,A1,A2,.,An。
你需要处理两种操作。
一种类型的操作是在给定的间隔内将一些给定的数字加到每个数字上。
另一种是要求在给定的时间间隔内求出数字的总和。
输入。
第一行包含两个数字N和Q.1≤N,Q≤100000。
第二行包含N个数字,A1,A2,.,an的初始值。
-1000000000≤AI≤1000000000。
接下来的Q行中的每一行代表一个操作。
“C a b c”是指将c加到Aa,Aa+1,.,Ab中的每一个。
-10000≤c≤10000。
“q a b”表示查询Aa,Aa+1,.,Ab之和。
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.
线段树经典题目//但是很麻烦很累人,需要用到lazy标记
//下次还是尽量用树状数组
lazy标记表示区间及以下的每个都要+lazy,标记区间以上的没有lazy,所以直接用num(增加值)算出来实际应该增加的值。
lazy每次都需要向下更新。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct inf
{
long long num;
long long lazy;
}tree[400100];
int f(int l,int r,int ln,int rn,int now,long long num)
{
if(ln<=l&&rn>=r)
{
tree[now].lazy+=num;//找到的区间lazy增加,表示此区间及以下的每个都要+lazy
if(l==r)
{
tree[now].num+=tree[now].lazy;//到叶子节点了,lazy无用,直接并入lazy
tree[now].lazy=0;
}
return 0;
}
tree[now].num+=(long long)(rn-ln+1)*num;//改变一路上的num值,也就是实际的区间和值
if(tree[now].lazy!=0)
{
tree[now*2].lazy+=tree[now].lazy;
tree[now*2+1].lazy+=tree[now].lazy;//lazy的更新(下放到子区间,更新实际值,lazy=0)
tree[now].num+=(long long)(r-l+1)*tree[now].lazy;
tree[now].lazy=0;
}
int temp=(l+r)/2;
if(rn<=temp)
{
f(l,temp,ln,rn,now*2,num);
}
else if(ln>=temp+1)
{
f(temp+1,r,ln,rn,now*2+1,num);
}
else
{
f(l,temp,ln,temp,now*2,num);
f(temp+1,r,temp+1,rn,now*2+1,num);
}
return 0;
}
long long check(int l,int r,int ln,int rn,int now)
{
if(ln<=l&&rn>=r)
{
if(l==r)
{
tree[now].num+=tree[now].lazy;
tree[now].lazy=0;//如上
}
return tree[now].num+(rn-ln+1)*tree[now].lazy;//如果有lazy,返回实际值加上还没有加上的lazy
}
if(tree[now].lazy!=0)
{
tree[now*2].lazy+=tree[now].lazy;
tree[now*2+1].lazy+=tree[now].lazy;
tree[now].num+=(long long)(r-l+1)*tree[now].lazy;//同上
tree[now].lazy=0;
}
int temp=(l+r)/2;
if(rn<=temp)
{
return check(l,temp,ln,rn,now*2);
}
else if(ln>=temp+1)
{
return check(temp+1,r,ln,rn,now*2+1);
}
else
{
return check(l,temp,ln,temp,now*2)+check(temp+1,r,temp+1,rn,now*2+1);
}
}
int main()
{
int i,j,k,n,t,m;long long l;
char ch[5];
scanf("%d",&n);
scanf("%d",&m);
for(i=1;i<=n;i++)
{
scanf("%d",&k);
f(1,n,i,i,1,k);
}
for(i=1;i<=m;i++)
{
scanf("%s",ch);
if(ch[0]=='C')
{
scanf("%d%d%lld",&j,&k,&l);
f(1,n,j,k,1,l);
}
else
{
scanf("%d%d",&j,&k);
printf("%lld\n",check(1,n,j,k,1));
}
}
return 0;
}