题意:
N个数,M次操作。每次操作 Q X Y 代表查询 X 到 Y 的区间和, C X Y Z 代表将区间 X 到 Y 中的所有数加 Z
思路:
分块区间修改,查询。
另:线段树解法
代码:
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const int MAXN=1e5+7;
int a[MAXN],n,m;
int num,l[MAXN],r[MAXN],belong[MAXN],blen;
long long sum[MAXN],lazy[MAXN];
void build(){
blen=sqrt((double)n);
num=n/blen;if(n%blen) num++;
for(int i=1;i<=num;i++) l[i]=(i-1)*blen+1,r[i]=i*blen;r[num]=n;
for(int i=1;i<=num;i++){
sum[i]=0;
lazy[i]=0;
for(int j=l[i];j<=r[i];j++){
belong[j]=i;
sum[i]+=a[j];
}
}
}
long long query(int st,int en){
long long ans=0;
if(belong[st]==belong[en]){
for(int i=st;i<=en;i++)
ans+=a[i]+lazy[belong[st]];
}else{
for(int i=st;i<=r[belong[st]];i++)
ans+=a[i]+lazy[belong[st]];
for(int i=belong[st]+1;i<=belong[en]-1;i++)
ans+=sum[i]+lazy[i]*(r[i]-l[i]+1);
for(int i=l[belong[en]];i<=en;i++)
ans+=a[i]+lazy[belong[en]];
}
return ans;
}
void update(int st,int en,long long v){
if(belong[st]==belong[en]){
for(int i=st;i<=en;i++)
a[i]+=v,sum[belong[st]]+=v;
}else{
for(int i=st;i<=r[belong[st]];i++)
a[i]+=v,sum[belong[st]]+=v;
for(int i=belong[st]+1;i<=belong[en]-1;i++)
lazy[i]+=v;
for(int i=l[belong[en]];i<=en;i++)
a[i]+=v,sum[belong[en]]+=v;
}
}
int main()
{
char op;
int l,r;
long long x;
while(scanf("%d%d",&n,&m)!=-1){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build();
for(int i=1;i<=m;i++){
getchar();
scanf("%c %d %d",&op,&l,&r);
if(op=='Q'){
printf("%lld\n",query(l,r));
}else{
scanf("%lld",&x);
update(l,r,x);
}
}
}
}