很妙的并查集,(有没有发现很多并查集多需要进行反向操作)
因为每次都会造成覆盖,不如反着来,每次对于没染色的点染色,每个染色的父亲是其右边,经过路压后就是此染色区间最右边
每个点只染一次O(n)
#include <cstdio> #include <algorithm> using namespace std; const int N=1e6+5; int clo[N],fa[N]; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} int main(){ int n,m,p,q; scanf("%d%d%d%d",&n,&m,&p,&q); for (int i=1;i<=n+2;i++) fa[i]=i;//细节,不加会RE for (int i=m;i>=1;i--){ int l=(i*p+q)%n+1,r=(i*q+p)%n+1; if (l>r) swap(l,r); for (int j=l;j<=r;){ int t=find(j); if (t==j){ clo[j]=i;fa[j]=j+1; } j=t; } } for (int i=1;i<=n;i++) printf("%d\n",clo[i]); }