关键:
- 数组空间4:二叉树节点数为2n-1,所有根节点下有两个空节点,所以节点数为4*n-1;
- lazy数组:因为修改范围已经包括整个区间,所以不再需要下放
- 函数模块:(build建树,down下放)+区间操作
- 注意:操作前下放,操作后赋值
代码:区间加法,区间求和
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long tree[400000],lazy[400000],ans;
void down(int num,int l,int r)
{
int mid=(l+r)>>1;
lazy[num*2]+=lazy[num];
tree[num*2]+=(mid-l+1)*lazy[num];
lazy[num*2+1]+=lazy[num];
tree[num*2+1]+=(r-mid)*lazy[num];
}
void build(int num,int l,int r)
{
if(l == r)
{
cin>>tree[num];
return;
}
int mid=(l+r)>>1;
build(num*2,l,mid);
build(num*2+1,mid+1,r);
tree[num]=tree[num*2]+tree[num*2+1];
}
void jia(int num,int l,int r,int ml,int mr,int k)
{
if(l >= ml && r <= mr)
{
lazy[num]+=k;
tree[num]+=(r-l+1)*k;
return;
}
int mid=(l+r)>>1;
down(num,l,r);
lazy[num]=0;
if(mid >= ml)
jia(num*2,l,mid,ml,mr,k);
if(mid < mr)
jia(num*2+1,mid+1,r,ml,mr,k);
tree[num]=tree[num]+(min(mr,r)-max(l,ml)+1)*k;
}
void getsum(int num,int l,int r,int ml,int mr)
{
if(l >= ml && r <= mr)
{
ans+=tree[num];
return;
}
int mid=(l+r)>>1;
down(num,l,r);
lazy[num]=0;
if(mid >= ml)
getsum(num*2,l,mid,ml,mr);
if(mid < mr)
getsum(num*2+1,mid+1,r,ml,mr);
}
int main()
{
cin>>n>>m;
build(1,1,n);
for(int i=1; i<=m; i++)
{
int x,y,z,k;
cin>>z>>x>>y;
if(z == 1)
{
cin>>k;
jia(1,1,n,x,y,k);
}
else
{
getsum(1,1,n,x,y);
cout<<ans<<endl;
ans=0;
}
}
return 0;
}
代码:区间加法、乘法,区间求和
#include<bits/stdc++.h>
using namespace std;
long long n,m,p;
long long tree[800000],lazy[800000],lazyz[800000],ans;
int getsum(int num,int l,int r,int ml,int mr);
关键代码
void down(int num,int l,int r)
{
int mid=(r+l)>>1;
tree[num*2]=(tree[num*2]*lazyz[num]+lazy[num]*(mid-l+1))%p;
tree[num*2+1]=(tree[num*2+1]*lazyz[num]+lazy[num]*(r-mid))%p;
lazyz[num*2]=(lazyz[num]*lazyz[num*2])%p;
lazyz[num*2+1]=(lazyz[num]*lazyz[num*2+1])%p;
lazy[num*2]=(lazy[num*2]*lazyz[num]+lazy[num])%p;
lazy[num*2+1]=(lazy[num*2+1]*lazyz[num]+lazy[num])%p;
lazy[num]=0;
lazyz[num]=1;
}
int getsum(int num,int l,int r,int ml,int mr)
{
int sum=0;
if(l >= ml && r <= mr)
{
return (tree[num]%p);
}
int mid=(l+r)>>1;
down(num,l,r);
if(mid >= ml)
sum+=getsum(num*2,l,mid,ml,mr);
if(mid < mr)
sum+=getsum(num*2+1,mid+1,r,ml,mr);
return sum%p;
}
void build(int num,int l,int r)
{
if(l == r)
{
cin>>tree[num];
lazyz[num]=1;
return;
}
int mid=(l+r)>>1;
build(num*2,l,mid);
build(num*2+1,mid+1,r);
tree[num]=(tree[num*2]+tree[num*2+1])%p;
lazyz[num]=1;
}
void jia(int num,int l,int r,int ml,int mr,int k)
{
if(l >= ml && r <= mr)
{
lazy[num]+=k;
tree[num]+=(r-l+1)*k;
return;
}
int mid=(l+r)>>1;
down(num,l,r);
if(mid >= ml)
jia(num*2,l,mid,ml,mr,k);
if(mid < mr)
jia(num*2+1,mid+1,r,ml,mr,k);
tree[num]=(tree[num]+(min(mr,r)-max(l,ml)+1)*k)%p;
}
void cheng(int num,int l,int r,int ml,int mr,int k)
{
if(l >= ml && r <= mr)
{
tree[num]=(tree[num]*k)%p;
lazy[num]=(lazy[num]*k)%p;
lazyz[num]=(lazyz[num]*k)%p;
return;
}
int mid=(l+r)>>1;
down(num,l,r);
if(mid >= ml)
cheng(num*2,l,mid,ml,mr,k);
if(mid < mr)
cheng(num*2+1,mid+1,r,ml,mr,k);
tree[num]=(tree[2*num]+tree[2*num+1])%p;
}
int main()
{
cin>>n>>m>>p;
build(1,1,n);
for(int i=1; i<=m; i++)
{
int x,y,z,k;
cin>>z>>x>>y;
if(z == 1)
{
cin>>k;
cheng(1,1,n,x,y,k);
}
else if(z == 2)
{
cin>>k;
jia(1,1,n,x,y,k);
}
else
{
ans=getsum(1,1,n,x,y);
cout<<ans<<endl;
}
}
return 0;
}