zoukankan      html  css  js  c++  java
  • [BZOJ2054]疯狂的馒头 并查集

    写点题庆祝一下自己的退役。

    其实是为了学习一下并查集。

    之前校内NOIP模拟赛(别说了,NOIP已经刮掉了)有一道题可以用并查集做,但是被我用强力剪枝水过去了。

    今天发现并查集好像是个非常好用的东西,似乎还挺强大的,所以来学习一下。

    突然发现并查集这东西好像有很多好的性质,要是明年的今天没有退役的话,或许可以来出些题目。

    看到这种题如果暴力用线段树做的话那么就是显然的(O(mlog n))显然做不了。

    那么考虑时间倒流,先染后面的色,这样如果染过色了的点就不需要再染了。

    那么我们现在就是需要想个办法保证,每个该被染色的点,被且只被染一次色,这样才能有复杂度保证。

    这里介绍一个新的技巧。

    我们维护一个东西,表示这个点右边(含自己)未被染色的第一个点(fa[x])。有了这个东西我们就可以直接跳过之间那些被染过色的点。

    考虑染完色以后,他的(fa[x])的值应该是和(fa[x+1])一样的。但是,只要(fa[x+1])的值被改掉了,(fa[x])也应该一起改。

    发现这种东西可以种并查集维护。

    然后具体实现看代码吧。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define REP(i,a,n) for(register int i(a);i<=(n);++i)
    #define PER(i,a,n) for(register int i(a);i>=(n);--i)
    #define dbg(...) fprintf(stderr,__VA_ARGS__)
    template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;}
    template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;}
    const int SZ=(1<<21)+1;char obuf[SZ+128],*oS=obuf,*oT=obuf+SZ-1;
    inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
    #define printf(...) oS>oT&&(flush(),1),oS+=sprintf(oS,__VA_ARGS__)
    struct IO_flusher{inline~IO_flusher(){flush();}}io_flusher;
    typedef long long ll;
    
    const int N=1e6+7,M=1e7+7;
    int n,m,p,q,col[N];
    
    int fa[N],stk[N]; 
    inline int Find(int x){while(fa[x]!=x)stk[++stk[0]]=x,x=fa[x];while(stk[0])fa[stk[stk[0]--]]=x;return x;}
    int main(){
    	scanf("%d%d%d%d",&n,&m,&p,&q);
    	REP(i,1,n)fa[i]=i;fa[n+1]=n+1;//错误笔记:Very important!!! 必须要把n+1自己存一下
    	PER(i,m,1){
    		int l=((ll)i*p+q)%n+1,r=((ll)i*q+p)%n+1;if(l>r)std::swap(l,r);
    		for(register int j=Find(l);j<=r;j=Find(j))col[j]=i,fa[j]=j+1;//错误笔记:这里不能写Union(j,j+1),因为这里要保证一定是指向右边的,如果按秩合并就会出问题。 
    	}
    	REP(i,1,n)printf("%d
    ",col[i]);
    }
    
  • 相关阅读:
    ZeptoLab Code Rush 2015
    UVa 10048 Audiophobia【Floyd】
    POJ 1847 Tram【Floyd】
    UVa 247 Calling Circles【传递闭包】
    UVa 1395 Slim Span【最小生成树】
    HDU 4006 The kth great number【优先队列】
    UVa 674 Coin Change【记忆化搜索】
    UVa 10285 Longest Run on a Snowboard【记忆化搜索】
    【NOIP2016提高A组模拟9.28】求导
    【NOIP2012模拟10.9】电费结算
  • 原文地址:https://www.cnblogs.com/hankeke/p/BZOJ2054.html
Copyright © 2011-2022 走看看