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\n",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\n",a[i]); }
AC!=correct 2019.05.06