题目描述 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);
}
}