bzoj2054疯狂的馒头(巧用非递归并查集)
www.cnblogs.com/shaokele/
bzoj2054:疯狂的馒头##
Time Limit: 10 Sec
Memory Limit: 162 MBDescription###
Input###
第一行四个正整数N,M,p,q
Output###
一共输出N行,第i行表示第i个馒头的最终颜色(如果最终颜色是白色就输出0)。
Sample Input###
4 3 2 4
Sample Output###
2
2
3
0
HINT
题目地址: 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;
}