RT
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
struct node{
ll l,r,w,lazy;
}trie[400005];
ll n,m,ans,num[100005];
inline void build_tree(ll l,ll r,ll pos)
{
trie[pos].l=l;
trie[pos].r=r;
if(l==r){
trie[pos].w=num[l];
return ;
}
int mid=(l+r)/2;
build_tree(l,mid,pos*2);
build_tree(mid+1,r,pos*2+1);
trie[pos].w=trie[pos*2].w+trie[pos*2+1].w;
}
inline void spread(ll pos)
{
if(trie[pos].lazy){
trie[pos*2].w+=(trie[pos*2].r-trie[pos*2].l+1)*trie[pos].lazy;
trie[pos*2+1].w+=(trie[pos*2+1].r-trie[pos*2+1].l+1)*trie[pos].lazy;
trie[pos*2].lazy+=trie[pos].lazy;
trie[pos*2+1].lazy+=trie[pos].lazy;
trie[pos].lazy=0;
}
}
inline void trie_plus(ll pos,ll x,ll y,ll k)
{
if(trie[pos].l>=x&&trie[pos].r<=y){
trie[pos].w+=k*(trie[pos].r-trie[pos].l+1);
trie[pos].lazy+=k;
return ;
}
spread(pos);
int mid=(trie[pos].l+trie[pos].r)/2;
if(x<=mid){
trie_plus(pos*2,x,y,k);
}
if(y>mid){
trie_plus(pos*2+1,x,y,k);
}
trie[pos].w=trie[pos*2].w+trie[pos*2+1].w;
}
inline ll search(ll pos,ll x,ll y)
{
if(trie[pos].l>=x&&trie[pos].r<=y){
return trie[pos].w;
}
spread(pos);
ll ans=0;
int mid=(trie[pos].l+trie[pos].r)/2;
if(x<=mid)
ans+=search(pos*2,x,y);
if(y>mid)
ans+=search(pos*2+1,x,y);
return ans;
}
int main()
{
scanf("%lld %lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&num[i]);
}
build_tree(1,n,1);
while(m--){
int a,x,y,k;
scanf("%lld",&a);
if(a==1){
scanf("%lld %lld %lld",&x,&y,&k);
trie_plus(1,x,y,k);
}
else{
scanf("%lld %lld",&x,&y);
printf("%lld\n",search(1,x,y));
}
}
return 0;
}
线段树这东西每次就是觉得自己想的很清楚,结果写出来就wa,极其苦恼