解题思路
还是模板题,直接上线段树的区间修改,区间查询。
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
int n,q,k,a,b,w,add[4000010],s[1000010];
long long sum[4000010];
void Add(int k,int l,int r,int v){
add[k]+=v;
sum[k]+=(long long)(r-l+1)*(long long)v;
}
void down(int k,int l,int r,int mid)
{
if(!add[k])return;
Add(k*2,l,mid,add[k]);
Add(k*2+1,mid+1,r,add[k]);
add[k]=0;
}
void change(int k,int l,int r,int x,int y,int v){
if(l>=x&&r<=y)
{
Add(k,l,r,v);
return;
}
int mid=(l+r)/2;
down(k,l,r,mid);
if(x<=mid)change(k*2,l,mid,x,y,v);
if(y>mid)change(k*2+1,mid+1,r,x,y,v);
sum[k]=sum[k*2]+sum[k*2+1];
}
long long query(int k,int l,int r,int x,int y,int v){
if(l>=x&&r<=y)
return sum[k];
int mid=(l+r)/2;
long long res=0;
down(k,l,r,mid);
if(x<=mid)res+=query(k*2,l,mid,x,y,v);
if(y>mid)res+=query(k*2+1,mid+1,r,x,y,v);
return res;
}
void build(int k,int l,int r){
if(l==r)
{
sum[k]=s[l];
return;
}
int mid=(l+r)/2;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
sum[k]=sum[k*2]+sum[k*2+1];
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&s[i]);
build(1,1,n);
for(int i=1;i<=q;i++)
{
scanf("%d",&k);
if(k==1)
{
scanf("%d%d%d",&a,&b,&w);
change(1,1,n,a,b,w);
}
if(k==2)
{
scanf("%d%d",&a,&b);
printf("%lld\n",query(1,1,n,a,b,w));
}
}
}