#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,q;
long long sum,a[200001];
struct tr
{
int l,r;
long long v,ad;
}s[2000001];
void build(int i,int l,int r)
{
s[i].l=l;s[i].r=r;
if(l==r)
{
s[i].v=a[l];return;
}
build(i*2,l,(l+r)/2);
build(i*2+1,(l+r)/2+1,r);
s[i].v=s[i*2].v+s[i*2+1].v;
}
void ask(int i,int ll,int rr)
{
if(s[i].ad!=0)
{
s[i].v+=s[i].ad*(s[i].r-s[i].l+1);
s[2*i].ad+=s[i].ad;
s[2*i+1].ad+=s[i].ad;
s[i].ad=0;
}
if(s[i].l>=ll&&s[i].r<=rr)
{
sum+=s[i].v;
return;
}
int kk=i*2;
if(s[kk].r>=ll)ask(kk,ll,rr);
if(s[kk+1].l<=rr)ask(kk+1,ll,rr);
}
void add(int i,int ll,int rr,int x)
{
if(s[i].l>=ll&&s[i].r<=rr)
{
s[i].ad+=x;
return;
}
if(ll>=s[i].l&&rr<=s[i].r)s[i].v+=x*(rr-ll+1);
else s[i].v+=x*(min(abs(s[i].r-ll+1),abs(rr-s[i].l+1)));
if(s[i].ad!=0)
{
s[i].v+=(s[i].r-s[i].l+1)*s[i].ad;
s[2*i].ad+=s[i].ad;
s[2*i+1].ad+=s[i].ad;
s[i].ad=0;
}
int kk=i*2;
if(s[kk].r>=ll)add(kk,ll,rr,x);
if(s[kk+1].l<=rr)add(kk+1,ll,rr,x);
}
int main ()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
cin>>q;
build(1,1,n);
for(int i=1;i<=q;i++)
{
int k;cin>>k;
if(k==1)
{
int b,c,d;
cin>>b>>c>>d;
add(1,b,c,d);
}
if(k==2)
{
int b,c;
cin>>b>>c;
sum=0;
ask(1,b,c);
cout<<sum<<endl;
}
}
}
codevs 1082 线段树练习3
最新推荐文章于 2019-03-01 20:39:00 发布
本文介绍了一种基于线段树的数据结构实现方法,用于高效处理区间加法和区间求和操作。通过递归构建、更新及查询线段树节点,能够快速响应大规模数据集上的区间操作请求。
720

被折叠的 条评论
为什么被折叠?



