codevs1191数轴染色 序列分块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs1191数轴染色 序列分块相关的知识,希望对你有一定的参考价值。

题目大意:
长度为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;
}



以上是关于codevs1191数轴染色 序列分块的主要内容,如果未能解决你的问题,请参考以下文章

codevs 1191 数轴染色

1191 数轴染色

数轴染色+并查集路径压缩+加速

CodeVS 数轴染色

codevs1170 双栈排序

CODEVS3037 线段覆盖 5[序列DP 二分]