如题,吾等废物如今刚开始补寒假的题。。。对寒假,五月份了,我还在寒假。。。
没有看板子,是手打的线段树,私心觉得套板子写题真的非常没有意义所以不愿意这么做。。。
不过每补一题对线段树的理解确实就深入很多,找到自己的节奏一点点来吧,不急不急
#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<iomanip>
#include<cstring>
#include<algorithm>
#define xf_dycm ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long int
#define ll long long
#define ull unsigned long long
using namespace std;
const int MAXN=2e6+10;
ll arr[MAXN];
struct Tree{
ll l,r;
ll sum;
ll lazy;
}tree[MAXN<<2];
void build_tree(ll i,ll L,ll R){
tree[i].l=L;tree[i].r=R;
if(L==R){
tree[i].sum=arr[L];
tree[i].lazy=0;
return;
}
ll mid=(L+R)/2;
build_tree(i*2,L,mid);
build_tree(i*2+1,mid+1,R);
tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
void spread(ll i){
if(tree[i].lazy!=0){
tree[i*2].sum+=tree[i].lazy*(tree[i*2].r-tree[i*2].l+1);
tree[i*2+1].sum+=tree[i].lazy*(tree[i*2+1].r-tree[i*2+1].l+1);
tree[i*2].lazy+=tree[i].lazy;
tree[i*2+1].lazy+=tree[i].lazy;
tree[i].lazy=0;
}
}
void change(ll i,ll st,ll ed,ll val){
if(tree[i].l>=st&&tree[i].r<=ed){
tree[i].sum+=val*(tree[i].r-tree[i].l+1);
tree[i].lazy+=val;
return;
}
if(tree[i].l>ed||tree[i].r<st){
return;
}
spread(i);//区别的关键步骤
change(i*2,st,ed,val);
change(i*2+1,st,ed,val);
tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
ll search(ll i,ll st,ll ed){
if(tree[i].l>=st&&tree[i].r<=ed){
return tree[i].sum;
}
if(tree[i].l>ed||tree[i].r<st){
return 0;
}
spread(i);//区别的关键步骤
return search(i*2,st,ed)+search(i*2+1,st,ed);//这步老是会忘记套函数然后疯狂debug。。。
}
//1 l r x 对a[l-r]+x
//2 l r 输出sum[l-r]
signed main(){
xf_dycm;
ll n,q;
cin>>n>>q;
for(ll i=1;i<=n;i++){
cin>>arr[i];
}
build_tree(1,1,n);
ll w;
ll st,ed,val;
while(q--){
cin>>w;
if(w==1){
cin>>st>>ed>>val;
change(1,st,ed,val);
}
else {
cin>>st>>ed;
cout<<search(1,st,ed)<<endl;
}
}
}