题意:
区间加,询问区间和。
思路:
黄学长的第一题,是单点询问,所以只要维护单点的值和块的值就好了,
这里是区间,要对块维护两个值,一个是块的加标记,另一个是块的总和。
具体操作代码很清楚。
PS:C++中sqrt有两个重载函数,一个参数是double,另一个是float。
所以传参最好强制转换一下~
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<math.h>
#include<algorithm>
typedef long long LL;
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
const int N=1e5+10;
LL n,m;
int be[N];
LL vtag[N],v[N],blo,sumtag[N];
void Query(int Left,int Right){
LL ans=0;
int temp;
temp=Right<be[Left]*blo?Right:be[Left]*blo;
for(int i=Left;i<=temp;i++)
ans=ans+v[i]+vtag[be[i]];
if(be[Left] != be[Right]){
for(int i=(be[Right]-1)*blo+1;i<=Right;i++)
ans=ans+v[i]+vtag[be[i]];
}
for(int i=be[Left]+1;i<=be[Right]-1;i++)
ans=ans+sumtag[i];
printf("%lld\n",ans);
}
void Update(int Left,int Right,LL val){
int temp;
temp=Right<be[Left]*blo?Right:be[Left]*blo;
for(int i=Left;i<=temp;i++)
{
v[i]=v[i]+val;
sumtag[be[i]]=sumtag[be[i]]+val;
}
if(be[Left] != be[Right]){
for(int i=(be[Right]-1)*blo+1;i<=Right;i++)
{
v[i]=v[i]+val;
sumtag[be[i]]=sumtag[be[i]]+val;
}
}
for(int i=be[Left]+1;i<=be[Right]-1;i++)
{
vtag[i]=vtag[i]+val;
sumtag[i]=sumtag[i]+val*blo;
}
}
int main(){
int Left,Right;
LL val;
char op[2];
scanf("%lld%lld",&n,&m);
blo = sqrt((double)n);
for(int i=1;i<=n;i++){
scanf("%lld",&v[i]);
be[i]=(i-1)/blo+1;
}
memset(sumtag,0,sizeof(sumtag));
memset(vtag,0,sizeof(vtag));
for(int i=1;i<=n;i++)
sumtag[be[i]]=sumtag[be[i]]+v[i];
while(m--){
scanf("%s",op);
if(op[0]=='Q'){
scanf("%d%d",&Left,&Right);
Query(Left,Right);
}
else
{
scanf("%d%d%lld",&Left,&Right,&val);
Update(Left,Right,val);
}
}
return 0;
}