样例能过,但测试数据全WA。
#include<bits/stdc++.h>
#define lson k<<1
#define rson k<<1|1
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll n,m;
ll num[4*N];
struct node{
ll l,r,add;
ll num;
}a[4*N]; //线段树 4倍空间
//下沉
void push_down(ll k){ //a[k].l ~ a[k].r 每个数加上 a[k].add
ll mid=(a[k].l+a[k].r)/2;
//左节点加上
a[lson].add+=a[k].add;
//左节点下边所有节点都要加,因此该节点的值就要加上 结点个数 X add
a[lson].num+=(mid-a[k].l+1)*a[k].add;
//右节点同理
a[rson].add+=a[k].add;
a[rson].num+=(a[k].r-mid)*a[k].add;
//取消该层懒标记
a[k].add=0;
}
void buildTree(ll k,ll x,ll y){ //k节点编号 x左范围 y右范围
a[k].l=x;
a[k].r=y;
if(x==y){ //叶子节点 直接赋值
a[k].num=num[x];
return;
}
buildTree(lson,x,(x+y)/2); //建立左子树
buildTree(rson,(x+y)/2+1,y); //建立右子树
a[k].num=a[lson].num+a[rson].num; //求该节点的值
}
ll sum(ll k,ll x,ll y){
//如果 x<=l<r<=y 那么这一段全部取走
if(x<=a[k].l&&a[k].r<=y){
return a[k].num;
}
push_down(k);
ll ans=0,mid=(a[k].l+a[k].r)/2;
//如果 x<=mid 说明有交叉 那么继续递归查找
if(x<=mid){
ans+=sum(lson,x,y); //查找范围不能变
}
if(y>=mid+1){
ans+=sum(rson,x,y);
}
return ans;
}
//区间修改 lazy-tag
void update(ll k,ll x,ll y,ll z){ //当前下标为 k 范围是 x~y 的值加上 z
if(x<=a[k].l&&a[k].l<=y){
a[k].add+=z;
//每个节点都要加 因此要加 结点个数 * z
a[k].num+=(a[k].r-a[k].l+1)*z;
return;
}
//下沉,把 a[k].add 分配给它的两条线段
push_down(k);
ll ans=0,mid=(a[k].l+a[k].r)/2;
//如果 x<=mid 说明有交叉 那么继续递归修改
if(x<=mid){
update(lson,x,y,z); //范围不能变
}
if(y>=mid+1){
update(rson,x,y,z);
}
a[k].num=a[lson].num+a[rson].num;
}
int main() {
cin>>n>>m;
for(ll i=1;i<=n;i++){
cin>>num[i];
}
buildTree(1,1,n);
ll x,y,z;
ll opt;
while(m--){
cin>>opt>>x>>y;
if(opt==1){
cin>>z;
update(1,x,y,z);
}
else{
cout<<sum(1,x,y)<<endl;
}
}
return 0;
}