長度爲n的序列,開始時全都是黑色的,m次操作,每次把[l,r]變成白色,求每次操作後剩下的黑點數。
分塊直接做。
設rest[i]表示第i塊剩下的個數,p爲每個點的裝填。
對於[l,r],找到l,r所處的塊lblock,rblock。
把lblock+1到rblock-1的塊的rest賦爲0,O(√n)。
然後判斷一下rest[lblock]是否空,如果不空則直接掃描更新rest和p,rblock同理。
注意這裏要判斷一下rest,因爲整體賦值的時候p沒有更新。
小結:對於分塊,塊數不能用unit+(unit*unit!=n),而要直接用(n-1)/unit+1。
#include <bits/stdc++.h>
using namespace std;
const int N=200010;
const int S=500;
int n,m,p[N];
int unit,num,rest[S],res;
inline int Read(void)
{
int s=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) s=s*10+c-'0';
return s*f;
}
int main(void)
{
n=Read();
unit=(int)sqrt(n),num=(n-1)/unit+1;
for (int i=1;i<=n;i++) p[i]=i;
for (int i=1;i<num;i++) rest[i]=unit; rest[num]=n-(num-1)*unit;
int l,r,lBlock,rBlock;
m=Read();
for (int i=1;i<=m;i++)
{
l=Read(),r=Read();
lBlock=(l-1)/unit+1,rBlock=(r-1)/unit+1;
if (lBlock==rBlock)
if (rest[lBlock])
for (int i=l;i<=r;i++)
if (p[i]) p[i]=0,rest[lBlock]--; else;
else;
else
{
for (int i=lBlock+1;i<=rBlock-1;i++) rest[i]=0;
if (rest[lBlock]) for (int i=l;i<=lBlock*unit;i++) if (p[i]) p[i]
=0,rest[lBlock]--;
if (rest[rBlock]) for (int i=(rBlock-1)*unit+1;i<=r;i++) if (p[i])
p[i]=0,rest[rBlock]--;
}
res=0;
for (int i=1;i<=num;i++) res+=rest[i];
printf("%d\n",res);
}
return 0;
}