LUOGU P2391 白雪皑皑

题目背景

“柴门闻犬吠,风雪夜归人”,冬天,不期而至。千里冰封,万里雪飘。空中刮起了鸭毛大雪。雪花纷纷,降落人间。 美能量星球(pty 在 spore 上的一个殖民地)上的人们被这美景所震撼。但是 pty 却不高兴,他不喜欢白色的世界,他觉得这样太单调了。所以他想对雪花进行染色,让世界变得多彩些。
题目描述

现在有 N 片雪花排成一列。 Pty 要对雪花进行 M 次染色操作,第 i次染色操作中,把第(i*p+q)%N+1 片雪花和第(i*q+p)%N+1 片雪花之间的雪花(包括端点)染成颜色 i。其中 p,q 是给定的两个正整数。他想知道最后 N 片雪花被染成了什么颜色。
输入输出格式
输入格式:

包含 4 行:

N M p q 意义如题中所述。

输出格式:

包含 N 行:

第 i 行表示第 i 片雪花被染成的颜色 c

输入输出样例
输入样例#1:

4
3
2
4

输出样例#1:

2
2
3
0

说明

20%的数据满足:1<=n,m<=1000

40%的数据满足:1<=n<=8000,1<=m<=1000000

80%的数据满足:1<=n<=500000,1<=m<=10000000

100%的数据满足:1<=n<=1000000,1<=m<=10000000

保证 1<=M*p+q,M*q+p<=2*10^9

解题思路

并查集+时光倒流,倒着做每次向后并,因为每个点最多只会被访问一次,所以复杂度可以承受。

代码

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
const int MAXN = 1000005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

int n,m,col[MAXN],p,q;
int fa[MAXN],l[10000005],r[10000005];

inline int get(int x){
    return x==fa[x]?x:fa[x]=get(fa[x]);
}

int main(){
    n=rd();m=rd();p=rd();q=rd();
    for(register int i=1;i<=n+1;i++) fa[i]=i;
    for(register int i=1;i<=m;i++) {
        l[i]=(i*p+q)%n+1;
        r[i]=(i*q+p)%n+1;
//      cin>>l[i]>>r[i];
        if(l[i]>r[i]) swap(l[i],r[i]);
//      cout<<l[i]<<" "<<r[i]<<endl;
    }
    for(register int i=m;i;i--){
        int L=l[i],R=r[i];
        for(register int j=L;j<=R;j++){
            if(!col[j]){
                int v=get(j+1);
                fa[j]=v;
                col[j]=i;
                j=v-1;
            }
            else j=get(j)-1;
        }
    }
    for(register int i=1;i<=n;i++)
        printf("%d
",col[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9676889.html