区间sum[rt]表示【l,r】区间有多多少个数被标记,setv[rt]为懒惰标记,表示标记的最左边的数。这样,标记的右边的数也能确定了。
这道题因为询问与更新的区间一致,因此只要同时询问与更新即可,但要注意次序。
#include<stdio.h>
#include<string.h>
int n,m,T,sum[4000000],setv[4000000],ans;
void pushdown(int rt,int l,int r)
{
int mid=(l+r)>>1;
if(setv[rt])
{
if(setv[rt]>mid)
{
setv[rt*2+1]=setv[rt];
sum[rt*2+1]=sum[rt];
}
else if(setv[rt]+sum[rt]-1<=mid)
{
setv[rt*2]=setv[rt];
sum[rt*2]=sum[rt];
}
else
{
setv[rt*2]=setv[rt];
sum[rt*2]=mid-setv[rt]+1;
setv[rt*2+1]=mid+1;
sum[rt*2+1]=setv[rt]+sum[rt]-mid-1;
}
setv[rt]=0;
}
}
void query(int rt,int l,int r,int x,int y)
{
if(x<=l&&y>=r)
{
ans+=r-l+1-sum[rt];
setv[rt]=l;
sum[rt]=r-l+1;
return;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if(x<=mid)
query(rt*2,l,mid,x,y);
if(y>mid)
query(rt*2+1,mid+1,r,x,y);
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(sum,0,sizeof(sum));
memset(setv,0,sizeof(setv));
int i,a,b;
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
ans=0;
query(1,1,n,a,b);
printf("%d\n",ans);
}
}
return 0;
}