[BZOJ2054]疯狂的馒头 并查集

链接

题意:N个点,M次操作,每次将 \([l,r]\) 染色,会覆盖之前的颜色,求最终每个点的颜色。\(N\le 10^6,M\le 10^7\)

题解

飞飞侠(链接)那题的优化,就是这里的思想。

将操作倒过来,那么每个点只会被染色一次

染色之后把 \(i\) 的父亲指向 \(i+1\) ,下一次弄的时候直接跳过

复杂度 \(O(\alpha(n)\times n)\)

#include<stdio.h>
#include<algorithm>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
template<typename T,typename U>inline bool smin(T&x,const U&y){return x>y?x=y,1:0;}
template<typename T,typename U>inline bool smax(T&x,const U&y){return x<y?x=y,1:0;}
const int N=1e6+5;
int n,m,p,q,fa[N],c[N];
inline int find(int x){return fa[x]?fa[x]=find(fa[x]):x;}
const int SZ=(1<<20)+7;
char buf[SZ+128],*S=buf,*T=buf+SZ;
inline void flush(){fwrite(buf,1,S-buf,stdout),S=buf;}
#define printf(...) S>T&&(flush(),1),S+=sprintf(S,__VA_ARGS__)
int main(){
    scanf("%d%d%d%d",&n,&m,&p,&q);
    for(int i=m;i;--i){
        int l=(i*p+q)%n+1,r=(i*q+p)%n+1;
        if(l>r)std::swap(l,r);
        for(int j=find(l);j<=r;j=find(j))c[j]=i,fa[j]=j+1;
    }
    REP(i,1,n)printf("%d\n",c[i]);
    return flush(),0;
}

猜你喜欢

转载自www.cnblogs.com/HolyK/p/9924848.html