BZOJ 2054 疯狂的馒头

Posted Driver_Lao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2054 疯狂的馒头相关的知识,希望对你有一定的参考价值。

Description

n个点,m次操作,每次把(i*p+q)%n+1与(i*q+p)%n+1之间的点染上颜色i,被染过色的会被新颜色覆盖,求最后每个点的颜色。

【题解】

因为被染过的颜色会被新的颜色覆盖,所以对于一个点,有效的染色只是最后一次。

那么我们可以倒着染色,已经染色的不染

求每个点被哪种区间覆盖或者某个区间是否已经被覆盖过都可以用并查集做。

我们把每个染过色的点都指向染色区间的右端点+1的位置,那么下一个没被染色的点就是find(x)

如果一个区间[l,r]满足find(l)>=r+1,那么这个区间已经被染色

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1000010;
int n,m,p,q,col[maxn],fa[maxn];
void read(int &k){
	k=0; int f=1; char c=getchar();
	while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
	while(‘0‘<=c&&c<=‘9‘)k=k*10+c-‘0‘,c=getchar();
	k*=f;
} 
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int main(){
	read(n); read(m); read(p); read(q); 
	for (int i=1;i<=n+1;i++) fa[i]=i;
	for (int i=m;i>=1;i--){
		int l=(1LL*i*p+q)%n+1,r=(1LL*i*q+p)%n+1; 
		if (l>r) swap(l,r);
		for (int j=find(l);j<=r;j=find(j)){
			col[j]=i;
			fa[j]=find(j+1);
		}
	}
	for (int i=1;i<=n;i++) printf("%d\n",col[i]);
	return 0;
}

 

以上是关于BZOJ 2054 疯狂的馒头的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2054 疯狂的馒头

Bzoj P2054 疯狂的馒头 | 并查集

BZOJ 2054 疯狂的馒头

bzoj2054: 疯狂的馒头(并查集)

BOZJ 2045:疯狂的馒头(并查集)

3284 疯狂的黄大神