【BZOJ 2054】 疯狂的馒头

2054: 疯狂的馒头

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 449   Solved: 175
[ Submit][ Status]

Description

Input

第一行四个正整数N,M,p,q

Output

一共输出N行,第i行表示第i个馒头的最终颜色(如果最终颜色是白色就输出0)。

Sample Input

4 3 2 4

Sample Output

2
2
3
0

HINT


并查集。


(一看这道题认为是简单的线段数打标记,但是数据范围显然不可以)

每个馒头的颜色取决于最后染他的是什么颜色,那么我们倒着来处理染色。


可是如何判断当前要染的区间是否在之前就被染过色了?


用并查集!!


f[i]表示i到f[i]-1这段区间已经被染过色了,那么我们把i染过色之后,f[i]=i+1。


处理一段区间,只要一直顺着f[i]染就可以了~


#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define M 10000000+5
using namespace std;
int f[M],n,m,p,q,c[M];
int Getfather(int x)
{
	if (f[x]==x||!f[x])
		return f[x]=x;
	return f[x]=Getfather(f[x]);
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&p,&q);
	int tot=0;
        for (int i=m;i;i--)
	{
		int l=((long long)i*p+q)%n+1,r=((long long)i*q+p)%n+1;
		if (l>r) swap(l,r);
		for (int k=Getfather(l);k<=r;k=Getfather(k))
		{
			c[k]=i;
			tot++;
			f[k]=k+1;
		}
		if (tot==n) break;
	}
	for (int i=1;i<=n;i++)
		printf("%d\n",c[i]);
	return 0;
}



感悟:

1.RE是因为没有处理f[n]=n+1


2.并查集维护区间信息~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值