P10665 [AMPPZ2013] Bytehattan 题解

· · 题解

第一眼:时光倒流做完了,这有紫??

第二眼:我丢强制在线,那咋办。

对啊那咋办。

当然是凉拌啦!

换个角度想想,我们可以画一个网格图出来然后模拟一下删边的过程,不难其实很难发现删边其实和合并两个格子是一样的效果。

最初这些格子都是互相分离的。 那么现在只需要思考在什么情况下,一条边两段的格点会从原本的连通变为不连通。 如果在合并这两个格子之前,**两个将要被合并的格子已经处于同一连通块了**,那么合并后必然会形成一个**环**,而这个环必然会**把环内外的格点分开**,使这条边两段的格点变得不连通了。否则没有分开情况发生,这两个格点还是连通的。 用并查集维护格子的连通情况即可。 忽略并查集常数 $\alpha(n^2)$ 的话,时间复杂度是 $O(k)$ 的,即 $O(n^2)$。 ::::success[code && [submission](https://www.luogu.com.cn/record/276519011)] ```cpp #include<bits/stdc++.h> #define LL long long #define UInt unsigned int #define ULL unsigned long long #define LD long double #define pii pair<int,int> #define pLL pair<LL,LL> #define pDD pair<LD,LD> #define fr first #define se second #define pb push_back #define isr insert #define _i128 __int128 using namespace std; const int N = 1505; const int N2 = N*N; int n,T,fa[N2],sz[N2],Ans=1; int read(){ int su=0,pp=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();} while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();} return su*pp; } int node(int x,int y){return (x-1)*n+y;} int FF(int u){return (fa[u]==u?u:fa[u]=FF(fa[u]));} void Merge(int u,int v){ u=FF(u),v=FF(v); if(u!=v)Ans=1,fa[v]=u,sz[u]+=sz[v]; else Ans=0;return; } int main(){ n=read(),T=read(); for(int i=1;i<n;i++)for(int j=1;j<n;j++) fa[node(i,j)]=node(i,j),sz[node(i,j)]=1; while(T--){ int x,y;char opt,tmp; if(Ans){ x=read(),y=read();cin>>opt; read(),read();cin>>tmp; }else{ read(),read();cin>>tmp; x=read(),y=read();cin>>opt; } if(opt=='N')Merge(node(x,y),node(x-1,y)); else Merge(node(x,y),node(x,y-1)); if(Ans)cout<<"TAK\n"; else cout<<"NIE\n"; } return 0; } ``` :::: 笑点解析: ![](https://cdn.luogu.com.cn/upload/image_hosting/xy0ylo4b.png) 注意到 `u=fa[u],v=fa[v];`,我在写什么东西。 警示后人(?)。 如果本篇题解对你有帮助的话,麻烦你点一个小小的赞,真是太感谢啦!