适用于操作数小,但数组长度大的。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll maxn=5e6+5;
ll n,m,cnt,rt;
struct node{
ll ls,rs,sum,tag;
}d[maxn];
void pushup(ll p){
d[p].sum=(d[p].ls?d[d[p].ls].sum:0)+(d[p].rs?d[d[p].rs].sum:0);
}
void pushdown(ll p,ll l,ll r){
ll mid=(l+r)/2;
if(d[p].tag){
if(!d[p].ls){
d[p].ls=++cnt;
}
if(!d[p].rs){
d[p].rs=++cnt;
}
d[d[p].ls].sum+=d[p].tag*(mid-l+1);
d[d[p].rs].sum+=d[p].tag*(r-mid);
d[d[p].ls].tag+=d[p].tag;
d[d[p].rs].tag+=d[p].tag;
d[p].tag=0;
}
}
void add(ll &p,ll l,ll r,ll x,ll y,ll k){
if(!p){
p=++cnt;
}
if(l>=x&&r<=y){
d[p].sum+=k*(r-l+1);
d[p].tag+=k;
return;
}
pushdown(p,l,r);
ll mid=(l+r)/2;
if(mid>=x){
add(d[p].ls,l,mid,x,y,k);
}
if(mid<y){
add(d[p].rs,mid+1,r,x,y,k);
}
pushup(p);
}
ll query(ll p,ll l,ll r,ll x,ll y){
if(!p){
return 0;
}
if(l>=x&&r<=y){
return d[p].sum;
}
pushdown(p,l,r);
ll mid=(l+r)/2,ans=0;
if(mid>=x){
ans+=query(d[p].ls,l,mid,x,y);
}
if(mid<y){
ans+=query(d[p].rs,mid+1,r,x,y);
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>m;
for(ll i=1;i<=m;i++){
ll opt,x,y,k;
cin>>opt>>x>>y;
if(opt==1){
cin>>k;
add(rt,1,n,x,y,k);
}else{
ll ans1=query(rt,1,n,x,y);
ll ans2=(x+y)*(y-x+1)/2;
cout<<ans1+ans2<<"\n";
}
}
return 0;
}