Bzoj P2054 疯狂的馒头 | 并查集

Posted wozaixuexi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj P2054 疯狂的馒头 | 并查集相关的知识,希望对你有一定的参考价值。

题目链接

思路:因为每次染色都会将某些馒头的颜色彻底更改,所以每个馒头的最终的颜色其实是由最后一次染色决定的,那么我们只考虑最后一次染色即可。对此,我们可以从后往前倒着染色,当目前的染色区间中存在白色馒头时,就将其染成当前的颜色,对于已经染过色的馒头则不处理,因为当前这一次染色已经不是其最后一次染色了,其最终颜色已经确定了。

对以上思路,考虑用经过路径压缩优化的并查集来维护在每个馒头右侧的、距离最近的、未染色的馒头的位置,以减小时间复杂度。

总时间复杂度O(m+n)。

代码:

#include<iostream>
#include<cstdio>
    using namespace std;
    int c[1000005],f[1000005];
int find(int x)
{
    if(f[x]==x) return x;
    return f[x]=find(f[x]);//路径压缩 
}
int main()
{
    int n=0,m=0,p=0,q=0;
    scanf("%d%d%d%d",&n,&m,&p,&q);
    for(int i=1;i<=n+1;i++) f[i]=i;//初始化 
    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 k=l;;)
        {
            int fx=find(k);
            k=f[fx];//向右找最近的未染色的馒头进行染色 
            if(k>r) break;//如果超过了染色区间范围则退出 
            c[k]=i;//染色 
            f[fx]=find(k+1);//向右合并,得出下一个最近的、在右边的未染色馒头的位置(画画图就明白了)            
        }
    }
    for(int i=1;i<=n;i++) printf("%d
",c[i]);
    return 0;
}

 

以上是关于Bzoj P2054 疯狂的馒头 | 并查集的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2054: 疯狂的馒头(并查集)

bzoj2054 疯狂的馒头

BZOJ 2054 疯狂的馒头

BOZJ 2045:疯狂的馒头(并查集)

BZOJ 2054 疯狂的馒头

[BZOJ3674]可持久化并查集加强版&[BZOJ3673]可持久化并查集 by zky