2.更新 要更新的区间值在L-R范围中,根据lazy-tag的原理 不用更新到每个根节点
实际上只需要在线段树已经分得的区间l-r中找出一个或多个包含在L-R中的l-r组成L-R
并且可以根据公式直接求得这个区间结点更新后的值
于是可以把函数分成3个部分
两个结束条件 结束条件1 要更新的区间不在l到r中 直接舍弃掉这个区间
结束条件2 找到了包含在L-R中的l-r区间 直接更新它 不再往后考虑
第3个部分 一部分的l-r属于L-R 需要分出有用的部分进行更新 无用的部分舍弃
并且一旦进行了拆分说明已经进入了子树 根据lazy-tag的原理,如果子节点之前的父节点恰好被更新到此停止 tag值不为0 我们就必须考虑利用父节点保存的tag值更新子节点 否则值会出错(会少加之前的tag)
所有代码:
#include <iostream>
using namespace std;
/*
1.创建
2.求和
3.更新
*/
long long a[100001];
struct tree
{
long long num;
int tag=0;
}t[400001];
void creat_tree(long long a[],tree t[],int node,int l,int r)
{
if(r==l)
{
t[node].num=a[r];
}
else
{
int mid=(l+r)/2;
creat_tree(a,t,node*2,l,mid);
creat_tree(a,t,node*2+1,mid+1,r);
t[node].num=t[node*2+1].num+t[node*2].num;
}
}
void update_tree(long long a[],tree t[],int node,int l,int r,int L,int R,int k)
{
if(L>r||R<l)//要更新的区间不在l到r的范围中
{
return;
}
else if(L<=l&&R>=r)//要更新的区间包含l到r的范围
{
t[node].num+=(r-l+1)*k;
t[node].tag+=k;//更新tag
}
else//部分包含
{
int mid=(l+r)/2;
if(t[node].tag!=0){
t[node*2].tag+=t[node].tag;//对右边子结点更新
t[node*2].num+=(mid-l+1)*t[node].tag;
t[node*2+1].tag+=t[node].tag;//对左边子结点更新
t[node*2+1].num+=(r-mid)*t[node].tag;
t[node].tag=0;}
update_tree(a,t,node*2,l,mid,L,R,k);
update_tree(a,t,node*2+1,mid+1,r,L,R,k);
t[node].num=t[node*2].num+t[node*2+1].num;
}
}
long long query_tree(long long a[],tree t[],int node,int l,int r,int L,int R)
{
long long query_l,query_r;
if(L>r||R<l)
{
return 0;
}
else if(L<=l&&R>=r)
{
return t[node].num;
}
else
{
int mid=(l+r)/2;
if(t[node].tag!=0){
t[node*2].tag+=t[node].tag;//对右边子结点更新
t[node*2].num+=(mid-l+1)*t[node].tag;
t[node*2+1].tag+=t[node].tag;//对左边子结点更新
t[node*2+1].num+=(r-mid)*t[node].tag;
t[node].tag=0;}
t[node].num=t[node*2].num+t[node*2+1].num;
query_l=query_tree(a,t,node*2,l,mid,L,R);
query_r=query_tree(a,t,node*2+1,mid+1,r,L,R);
}
return query_l+query_r;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
creat_tree(a,t,1,1,n);
int temp;int x,y,k;
while(m--)
{
cin>>temp;
if(temp==2)
{
cin>>x>>y;
cout<<query_tree(a,t,1,1,n,x,y)<<endl;
}
else if(temp==1)
{
cin>>x>>y>>k;
update_tree(a,t,1,1,n,x,y,k);
}
}
return 0;
}