线段树区间覆盖问题,主要难点在于lazy标签要怎么用,我们可以定义lazy标签标示对于根节点now来说,他的整个区间也就是[now.l,now.r]是以now.lazy为首项的等差数列,以及作为区间覆盖的标准的话,那这道题和普通的区间覆盖就没有区别了,当然还有别的做法。
#include<iostream>
using namespace std;
const int N=2e5+10;
typedef long long ll;
struct node
{
int l,r;
ll v,lazy;
}tree[4*N];
int n,m;
ll getnum(ll x,ll len)
{
ll ans=0;
ans=(x+x+len-1)*len/2;
return ans;
}
void build(int l,int r,int now)
{
tree[now].l=l;
tree[now].r=r;
int mid=(l+r)/2;
if(l==r){
cin>>tree[now].v;return;
}
else{
build(l,mid,now*2);
build(mid+1,r,now*2+1);
}
tree[now].v=tree[now*2].v+tree[now*2+1].v;
return;
}
void pushdown(int now)
{
int mid=(tree[now].l+tree[now].r)/2;
int num=tree[now].lazy;
int l=tree[now].l;
int r=tree[now].r;
tree[2*now].v=getnum(num,mid-l+1);
tree[2*now].lazy=num;
tree[2*now+1].v=getnum(num+mid+1-l,r-mid);
tree[2*now+1].lazy=num+mid+1-l;
tree[now].lazy=0;
return;
}
void update(int num,int l,int r,int now)
{
// cout<<l<<" "<<r<<endl;
int mid=(tree[now].l+tree[now].r)/2;
if(tree[now].l==l&&tree[now].r==r)
{
tree[now].v=ll(num+num+r-l)*(r-l+1)/2;
tree[now].lazy=num;
return;
}
if(tree[now].lazy!=0)pushdown(now);
if(r<=mid)update(num,l,r,2*now);
else if(l>=mid+1)update(num,l,r,2*now+1);
else
{
update(num,l,mid,2*now);
update(num+mid+1-l,mid+1,r,2*now+1);
}
tree[now].v=tree[2*now].v+tree[2*now+1].v;
return;
}
ll getsum(int l,int r,int now)
{
int mid=(tree[now].l+tree[now].r)/2;
if(tree[now].l==l&&tree[now].r==r)return tree[now].v;
if(tree[now].lazy!=0)pushdown(now);
ll ans=0;
if(r<=mid)ans+=getsum(l,r,2*now);
else if(l>=mid+1)ans+=getsum(l,r,2*now+1);
else ans+=getsum(l,mid,2*now)+getsum(mid+1,r,2*now+1);
return ans;
}
int main ()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m;
build(1,n,1);//建树
int op,l,r,k;
while(m--)
{
cin>>op;
if(op==1)
{
cin>>l>>r>>k;
update(k,l,r,1);
}
else
{
cin>>l>>r;
cout<<getsum(l,r,1)<<endl;
}
}
}


京公网安备 11010502036488号