[BZOJ 2054]疯狂的馒头(并查集)
Description
CQF十分喜欢吃馒头。兴奋之下他一下子买了N 个馒头请所有认识他的人吃。
但是CQF不喜欢白色,喜欢红色、黄色、绿色等鲜艳的颜色。于是他把所有白色的馒头排成一列。然后进行M 次染色操作。每个染色操作都是用一个神奇的刷子把连续的多个馒头染成特定的某种颜色。一个馒头最终的颜色是最后一次染它的颜色。如果一个馒头没有被染过色,那么它的颜色就是白色。现在CQF已经定好了染色计划:在第i次染色操作中,把第(i × p + q)mod N + 1个馒头和第(i × q + p)mod N + 1个馒头之间的馒头染成颜色i,其中p, q是特定的两个正整数。他想立即知道最后每个馒头的颜色。你能帮他吗?
Solution
从m到1倒序染色,染色的同时将该点与右边合并,保证每个点只染色一次
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; #define MAXN 1000005 int n,m,col[MAXN],father[MAXN],p,q,cnt=0; int find(int x) { if(father[x]==x)return x; return father[x]=find(father[x]); } int main() { scanf("%d%d%d%d",&n,&m,&p,&q); for(int i=1;i<=n+1;i++)father[i]=i; for(int i=m;i>0;i--) { int l=(i*p%n+q)%n+1,r=(i*q%n+p)%n+1; if(l>r)swap(l,r); for(int j=find(l);j<=r;j=find(j)) {col[j]=i,father[j]=j+1,cnt++;} if(cnt>n)break; } for(int i=1;i<=n;i++)printf("%d\n",col[i]); return 0; }