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
The sums may exceed the range of 32-bit integers.
题意: 输入N,Q 。 N表示有几个数,以下Q行表示有几个操作, 如果输入为C, a, b, c 代表从第a个数开始到第b个数结束,每个数都加c;Q, a, b表示查询从第a个数到第b个数区间内的和并输出。
#include<iostream>
#include<stack>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<math.h>
using namespace std;
# define ll long long
const int maxn = 1e6+100;
int n, m;
ll mapp[maxn],sum[maxn],add[maxn];
int l[maxn],r[maxn];
int belong[maxn];
//常规操作;
void build()
{
int block = (int)sqrt(n*1.0);//每块的大小;
//块数;
int num=n/block;
if(n%block)
num++;
//每个数属于哪一块;
for(int i=1; i<=n; i++)
{
belong[i]=(i-1)/block+1;
}
//该数所在块的左边界和右边界;
for(int i=1; i<=num; i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}
r[num]=n;//最后一个数的右边界一定为n;
//第i块内包含数的和为 sum[i],(计算每一块的和);
for(int i=1; i<=num; i++)
{
for(int j=l[i];j<=r[i];j++)
{
sum[i]+=mapp[j];
}
}
}
//区间的更新;
void update(int x, int y, ll val)
{
//如果给定的两个点属于同一块(特殊情况),那么就直接在其点上+val,区间和+(y-x+1)val;
if(belong[x]==belong[y])
{
for(int i=x; i<=y; i++)
{
mapp[i]+=val;
sum[belong[x]]+=val;
}
return ;
}
//对于x所在块,从x开始到x所在块右边界结束,进行同上操作;
for(int i=x; i<=r[belong[x]]; i++)
{
mapp[i]+=val;
sum[belong[x]]+=val;
}
//对于y所在块,从y所在块的左边界开始到y结束,进行同上上操作;
for(int i=l[belong[y]]; i<=y; i++)
{
mapp[i]+=val;
sum[belong[y]]+=val;
}
//对于除去x所在块和y所在块之外,中间的每一块;
for(int i=belong[x]+1; i<belong[y]; i++)
{
add[i]+=val;
}
}
//访问区间[x, y];
ll ask(int x,int y)
{
ll ans=0;
//如果所查询区间刚好在一个块里(特殊情况);
if(belong[x]==belong[y])
{
for(int i=x; i<=y; i++)
{
ans+=mapp[i]+add[belong[x]];
}
return ans;
}
//在循环x所在块内的数字时,每次要加上add[belong[x]];
for(int i=x; i<=r[belong[x]];i++)
{
ans+=mapp[i]+add[belong[x]];
}
//在循环y所在块内的数字时,每次要加上add[belong[x]];
for(int i=l[belong[y]]; i<=y; i++)
{
ans+=mapp[i]+add[belong[y]];
}
//除了x和y所在块,循环每一块时,都要加上每一块的包含的数字个数*add[i]即:+add[i]*(r[i]-l[i]+1)
for(int i=belong[x]+1;i<belong[y];i++)
{
ans+=sum[i]+add[i]*(r[i]-l[i]+1);
}
return ans;
}
int main()
{
scanf("%d %d",&n, &m);
for(int i=1; i<=n; i++)
{
scanf("%lld", &mapp[i]);
}
build();
char str[10];
int x, y;
ll cost;
while(m--)
{
scanf("%s", str);
if(str[0]=='Q')
{
scanf("%d %d",&x,&y);
printf("%lld\n",ask(x, y));
}
else if(str[0]=='C')
{
scanf("%d %d %lld",&x,&y,&cost);
update(x, y, cost);
}
}
return 0;
}