在一条数轴上有N个点,分别是1~N。一开始所有的点都被染成黑色。接着
我们进行M次操作,第i次操作将[Li,Ri]这些点染成白色。请输出每个操作执行后
剩余黑色点的个数。
输入一行为N和M。下面M行每行两个数Li、Ri
输出M行,为每次操作后剩余黑色点的个数。
10 3
3 3
5 7
2 8
9
6
3
数据限制
对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); } }