Description
CQF十分喜欢吃馒头。兴奋之下他一下子买了N个馒头请所有认识他的人吃。但是CQF不喜欢白色,喜欢红色、黄色、绿色等鲜艳的颜色,于是他把所有白色的馒头排成一列。然后进行M次染色操作。每个染色操作都是用一个神奇的刷子把连续的多个馒头染成特定的某种颜色。一个馒头最终的颜色是最后一次染它的颜色。如果一个馒头没有被染过色,那么它的颜色就是白色。现在CQF已经定好了染色计划;在第i次染色操作中,把第(ip+q)mod N+ 1个馒头和第(iq+p)mod N+1个馒头之间的馒头染成颜色i,其中p,q是特定的两个正整数。他想立即知道最后每个馒头的颜色。你能帮他吗?
Input
输入文件仅一行为四个正整数N,M,p,q。
Output
输出文件一共N行,第i行表示第i个馒头的最终颜色(如果最终颜色是白色就输出0)。
Sample Input
4 3 2 4
Sample Output
2
2
3
0
Hint
【数据范围】:
在20%的数据中,1<=N<=1000,1<=M<=10000;
在40%的数据中,1<=N<=10000,1<=M<=100000;
在60%的数据中,1<=N<=50000,1<=M<=500000;
在80%的数据中,1<=N<=300000,1<=M<=3000000;
在100%的数据中,1<=N<=1000000,1<=M<=10000000;
保证所有的输入数据中1<=Mp+q,Mq+p<=2^31-1
思路
- 并查集+贪心套路:操作倒着处理
- 用并查集维护每个馒头后面第一个白馒头(包括自己),然后每次染色暴力染区间内所有空馒头,同时把染了色的馒头的集合和后面一个的集合进行合并。(
有点链表的感觉?
代码
#include <iostream>
#include <cstdio>
#define maxn 1000005
using namespace std;
int fa[maxn],num[maxn];
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
int main()
{
int n,m,q,p; scanf("%d%d%d%d",&n,&m,&p,&q);
for(int i=1;i<=n+1;++i) fa[i]=i;//跳了很久,1~n+1
for(int i=m;i;--i)
{
int left=(i*p+q)%n+1,right=(i*q+p)%n+1;
if(left>right) swap(left,right);
for(int j=getfa(left);j<=right;j=getfa(j)) num[j]=i,fa[j]=j+1;
}
for(int i=1;i<=n;++i) printf("%d
",num[i]);
return 0;
}