zkw线段树模板练习。
orz今天写了三遍
另外我只写了区间修改和求和。为啥呢?因为我菜啊qwq
#include<iostream>
#include<cstdio>
#define maxn 200001
#define int long long
using namespace std;
int n, m;
int sum[maxn*2], add[maxn*2];
void build(){
for(m=1; m<=n; m<<=1);
for(int i=m+1; i<=m+n; i++)
scanf("%lld", &sum[i]);
for(int i=m-1; i; i--)
sum[i]=sum[i<<1]+sum[i<<1|1];
}
inline int query_part(int s, int t){
int lc=0, rc=0, len=1, ans=0;
for(s+=m-1, t+=m+1; s^t^1; s>>=1, t>>=1, len<<=1){
if(s&1^1) ans+=sum[s^1]+len*add[s^1], lc+=len;
if(t&1) ans+=sum[t^1]+len*add[t^1], rc+=len;
if(add[s>>1]) ans+=add[s>>1]*lc;
if(add[t>>1]) ans+=add[t>>1]*rc;
}
s>>=1;
for(lc+=rc; s; s>>=1)
if(add[s]) ans+=add[s]*lc;
return ans;
}
inline int update(int s, int t, int v){
int lc=0, rc=0, len=1;
for(s+=m-1, t+=m+1; s^t^1; s>>=1, t>>=1, len<<=1){
if(s&1^1) add[s^1]+=v, lc+=len;
if(t&1) add[t^1]+=v, rc+=len;
sum[s>>1]+=v*lc, sum[t>>1]+=v*rc;
}
for(lc+=rc; s; s>>=1)
sum[s>>1]+=v*lc;
}
int q;
signed main(){
scanf("%lld%lld", &n, &q);
build();
int qwq, x, y, k;
while(q--){
scanf("%lld", &qwq);
if(qwq==1){
scanf("%lld%lld%lld", &x, &y, &k);
update(x, y, k);
}else{
scanf("%lld%lld", &x, &y);
printf("%lld\n", query_part(x, y));
}
}
return 0;
}
不如吃茶去