zoukankan      html  css  js  c++  java
  • Luogu P2391 白雪皑皑 && BZOJ 2054: 疯狂的馒头 并查集

    4月的时候在luogu上做过 白雪皑皑 这道题,当时一遍AC可高兴了qwq,后来去了个厕所,路上忽然发现自己的做法是错的qwq。。。然后就咕咕了qwq

    今天看到了 疯狂的馒头 ,发现一毛一样OvO。。。还是好好做一下吧QWQ

    先上个错误代码(虽然BZOJ和Luogu都A了)

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #define R register int
    #define getchar() *S++
    using namespace std;
    char RR[50000005],*S=RR;
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    int n,m,p,q;
    int vl[1000010],pre[1000010],nxt[1000010];
    signed main() {
        fread(RR,sizeof(RR),1,stdin);
        n=g(),m=g(),p=g(),q=g();
        for(R i=1;i<=n;++i) pre[i]=i-1,nxt[i]=i+1;
        for(R i=m;i>=1;--i) {R l=(i*p+q)%n+1,r=(i*q+p)%n+1; if(l>r) swap(l,r);
            if(!vl[l]) for(R j=l;j<=r;j=nxt[j]) vl[j]=i,nxt[pre[j]]=nxt[j],pre[nxt[j]]=pre[j];
            if(!vl[r]) for(R j=r;j>=l;j=pre[j]) vl[j]=i,nxt[pre[j]]=nxt[j],pre[nxt[j]]=pre[j];
        } for(R i=1;i<=n;++i) printf("%d
    ",vl[i]); 
    }
    

    首先倒序处理显然吧。。。已经染过色的就不用再染了。。

    但是这样判断显然是不对的:只判了左右端点不能确定中间有没有染色。。。问题是不能动态更新fa

    刚刚本来想hack一下自己,结果发现不会造数据。。。。莫非这数据是有规律的导致我AC了???不知。。。懒得对拍了。。。如果大佬有想法可以评论,救救这只不知所对(不知所错)的蒟蒻、、qwq

    好,扯完皮说正解:

    用并查集当做链表(???)。。。还是倒序处理,如果这个区间已经染了,那么向右合并。注意每次读取fa时是要用getf来路径压缩,而不能直接取fa,否则不能更新

    #include<cstdio>
    #include<iostream>
    #define R register int
    using namespace std;
    const int N=1E+6,M=1E+7;
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    int n,m,p,q,cnt;
    int fa[N],a[N];
    inline int getf(int x) {return x==fa[x]?x:fa[x]=getf(fa[x]);}
    signed main() { 
        n=g(),m=g(),p=g(),q=g(); 
        for(R i=1;i<=n+1;++i) fa[i]=i;
        for(R i=m;i;--i) { R l=(i*p+q)%n+1,r=(i*q+p)%n+1;
            if(l>r) swap(l,r);
            for(R j=getf(l);j<=r;j=getf(j)) {a[j]=i,fa[j]=j+1,++cnt; if(cnt==n) break;}
            if(cnt==n) break;
        } for(R i=1;i<=n;++i) printf("%d
    ",a[i]);
    }

    AC!=correct 2019.05.06

  • 相关阅读:
    Note/Solution 转置原理 & 多点求值
    Note/Solution 「洛谷 P5158」「模板」多项式快速插值
    Solution 「CTS 2019」「洛谷 P5404」氪金手游
    Solution 「CEOI 2017」「洛谷 P4654」Mousetrap
    Solution Set Border Theory
    Solution Set Stirling 数相关杂题
    Solution 「CEOI 2006」「洛谷 P5974」ANTENNA
    Solution 「ZJOI 2013」「洛谷 P3337」防守战线
    Solution 「CF 923E」Perpetual Subtraction
    KVM虚拟化
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10819384.html
Copyright © 2011-2022 走看看