bzoj2054疯狂的馒头(巧用非递归并查集)

www.cnblogs.com/shaokele/


bzoj2054:疯狂的馒头##

  Time Limit: 10 Sec
  Memory Limit: 162 MB

Description###

  p1
 

Input###

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

Output###

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

Sample Input###

  4 3 2 4
 

Sample Output###

  2
  2
  3
  0
  

HINT

  p2
  

题目地址:  bzoj2054:疯狂的馒头

题目大意:   题目很简洁了:)####

  

题解:

  并查集巧用
  因为颜色是覆盖上去的
  所以我们只要考虑最后一次染了什么颜色就可以了
  倒着做上来
  对于一个染色的区间 \(l,r\) ,我们只要将 \(l\) 指向 \(r+1\) 就好了,类似链表的操作
  用并查集维护操作
  
  本地测要加栈 或者 用非递归并查集
  不然无限RE
  数据下载[data](https://files.cnblogs.com/files/shaokele/2054.zip)
  


AC代码

#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e6+5;
int n,m,p,q,l,r,sum;
int fa[N],ans[N];
int find(int x){
	int p=x;
	while(p!=fa[p])
		p=fa[p];
	while(x!=p){
		int tmp=fa[x];
		fa[x]=p;
		x=tmp;
	}
	return x;
}
int main(){
	scanf("%d%d%d%d",&n,&m,&p,&q);
	for(int i=1;i<=n+1;i++)
		fa[i]=i;
	for(int i=m;i>=1;i--){
		l=(1ll*i*p+q)%n+1;
		r=(1ll*i*q+p)%n+1;
		if(l>r)swap(l,r);
		for(int k=find(l);k<=r;k=find(k)){
			ans[k]=i;
			fa[k]=k+1;
			sum++;
			if(sum==n)break;
		}
		if(sum==n)break;
	}
	for(int i=1;i<=n;i++)
		printf("%d\n",ans[i]);
	return 0;
}
posted @ 2018-05-31 09:08  skl_win  阅读(260)  评论(0编辑  收藏  举报
Live2D