【codevs1191】数轴染色

题目描述 Description

在一条数轴上有N个点,分别是1~N。一开始所有的点都被染成黑色。接着
我们进行M次操作,第i次操作将[Li,Ri]这些点染成白色。请输出每个操作执行后
剩余黑色点的个数。

输入描述 Input Description

输入一行为N和M。下面M行每行两个数Li、Ri

输出描述 Output Description

输出M行,为每次操作后剩余黑色点的个数。

样例输入 Sample Input

10 3
3 3
5 7
2 8

样例输出 Sample Output

9
6
3

数据范围及提示 Data Size & Hint

数据限制
对30%的数据有1<=N<=2000,1<=M<=2000
对100%数据有1<=Li<=Ri<=N<=200000,1<=M<=200000

【题解】

sum[now]表示这个区间有没有被完全染色。bool

【代码】

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,lrange,rrange,ans;
bool sum[5000000],delta[5000000];
inline void update(int now){
	sum[now]=sum[now<<1]&&sum[(now<<1)+1];
}
inline void pushdown(int now,int l,int r,int mid){
	if (delta[now]){
		sum[now<<1]=true;
		delta[now<<1]=true;
		sum[(now<<1)+1]=true;
		delta[(now<<1)+1]=true;
		delta[now]=false;
	}
}
inline void interval_change(int now,int l,int r,int lrange,int rrange){
	int mid=(l+r)>>1;
	pushdown(now,l,r,mid);
	if (lrange<=l&&r<=rrange){
		sum[now]=true;
		delta[now]=true;
		return;
	}
	if (lrange<=mid)
	  interval_change(now<<1,l,mid,lrange,rrange);
	if (mid+1<=rrange)
	  interval_change((now<<1)+1,mid+1,r,lrange,rrange);
	update(now);
}
inline int query(int now,int l,int r,int lrange,int rrange){
	int mid=(l+r)>>1,ans=0;
	pushdown(now,l,r,mid);
	if (lrange<=l&&r<=rrange&&sum[now])
	  return r-l+1;
	if (l==r) return sum[now];//这句不加会出错。因为如果递归到叶子并且它没有被染色那么就返回0,否则的话就还会往下递归下去导致出错
	if (lrange<=mid)
	  ans+=query(now<<1,l,mid,lrange,rrange);
	if (mid+1<=rrange)
	  ans+=query((now<<1)+1,mid+1,r,lrange,rrange);
	return ans;
}
int main(){
	scanf("%d",&n);
	scanf("%d",&m);
	for (int i=1;i<=m;++i){
		scanf("%d%d",&lrange,&rrange);
		interval_change(1,1,n,lrange,rrange);
		ans=query(1,1,n,1,n);
	    printf("%d\n",n-ans);
	}
}



你可能感兴趣的:(线段树,codevs)