bzoj2054疯狂的馒头(巧用非递归并查集)

www.cnblogs.com/shaokele/


bzoj2054:疯狂的馒头

  Time Limit: 10 Sec
  Memory Limit: 162 MB

Description

  p1
 

Input

  第一行四个正整数N,M,p,q
 

Output

  一共输出N行,第i行表示第i个馒头的最终颜色(如果最终颜色是白色就输出0)。
 

Sample Input

  4 3 2 4
 

Sample Output

  2
  2
  3
  0
  

HINT

  p2
  

题目地址:  bzoj2054:疯狂的馒头

题目大意:   题目很简洁了:)

  

题解:

  并查集巧用
  因为颜色是覆盖上去的
  所以我们只要考虑最后一次染了什么颜色就可以了
  倒着做上来
  对于一个染色的区间 \(l,r\) ,我们只要将 \(l\) 指向 \(r+1\) 就好了,类似链表的操作
  用并查集维护操作
  
  本地测要加栈 或者 用非递归并查集
  不然无限RE
  数据下载[data](https://files.cnblogs.com/files/shaokele/2054.zip)
  


AC代码

#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e6+5;
int n,m,p,q,l,r,sum;
int fa[N],ans[N];
int find(int x){
    int p=x;
    while(p!=fa[p])
        p=fa[p];
    while(x!=p){
        int tmp=fa[x];
        fa[x]=p;
        x=tmp;
    }
    return x;
}
int main(){
    scanf("%d%d%d%d",&n,&m,&p,&q);
    for(int i=1;i<=n+1;i++)
        fa[i]=i;
    for(int i=m;i>=1;i--){
        l=(1ll*i*p+q)%n+1;
        r=(1ll*i*q+p)%n+1;
        if(l>r)swap(l,r);
        for(int k=find(l);k<=r;k=find(k)){
            ans[k]=i;
            fa[k]=k+1;
            sum++;
            if(sum==n)break;
        }
        if(sum==n)break;
    }
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shaokele/p/9114804.html