P2391 白雪皑皑

白雪皑皑 - 洛谷

“柴门闻犬吠,风雪夜归人”,冬天,不期而至。千里冰封,万里雪飘。空中刮起了鸭毛大雪。雪花纷纷,降落人间。 美能量星球(pty 在 spore 上的一个殖民地)上的人们被这美景所震撼。但是 pty 却不高兴,他不喜欢白色的世界,他觉得这样太单调了。所以他想对雪花进行染色,让世界变得多彩些。

题目描述

现在有 n 片雪花排成一列。 pty 要对雪花进行 m 次染色操作,第 i 次染色操作中,把第((i×p+q)modn)+1 片雪花和第 ((i×q+p)modn)+1 片雪花之间的雪花(包括端点)染成颜色 i。其中 p,q 是给定的两个正整数。他想知道最后 n 片雪花被染成了什么颜色。没有被染色输出 0。

输入格式

输入共四行,每行一个整数,分别为 n,m,p,q,意义如题中所述。

输出格式

输出共 n 行,每行一个整数,第 i 行表示第 i 片雪花的颜色。

题解:这题还怪有意思的嘞。一开始会去想双链表,后来发现过不了。染色有个规律:后染的会覆盖前染的,所以我们没有必要模拟过程。直接从后往前扫,根据他的规则染色,过于避免颜色被覆盖的问题,我们可以用并查集,染过色的区块我们使它的父亲为最靠前没染色的区块,这样节省了大量搜索的时间(有点像KMP)。
然后用一个数组储存颜色,就这样(还有些细节要注意):

	#include<bits/stdc++.h>
	using namespace std;
	const int INF=1e6+3;
	int n,m,p,q,fa[INF],color_[INF];
	int find_(int x)
	{
		if(x==fa[x])
		{
			return x;
		}
		return fa[x]=find_(fa[x]);
	}
	void paint_()
	{
		for(int i=m;i>=1;i--)//从后往前扫
		{
			int l1=(i*p+q)%n+1,r1=(i*q+p)%n+1;
			if(l1>r1)
			{
				swap(l1,r1);//保证循环有效(原题说之间,没说哪个大)
			}
			for(int j=r1;j>=l1;)//这个j也需要从后往前扫,避免回溯卡死
			{
				int index=find_(j);
				if(index==j)//如果这个点没染过
				{
					color_[j]=i;//储存颜色
					fa[j]=find_(j-1);//将它的父亲设为上一个点
				}
				j=fa[j];//维护
			 } 
		}
	}
	int main()
	{
		cin>>n>>m>>p>>q;
		for(int i=1;i<=n;i++)
		{
			fa[i]=i;//初始化!!
		}
		paint_();
		for(int i=1;i<=n;i++)
		{
			printf("%d\n",color_[i]);
		}
	}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值