E. Binary Matrix(dsu&滚动)

考虑空间限制,采用滚动数组维护 d s u dsu dsu

注意合并的时候向左上合并,这样下一行状态才能继续更新。

时间复杂度: O ( n m l o g m ) O(nmlogm) O(nmlogm)

// Problem: E. Binary Matrix
// Contest: Codeforces - Educational Codeforces Round 31
// URL: https://codeforces.ml/problemset/problem/884/E
// Memory Limit: 16 MB
// Time Limit: 3000 ms
// Date: 2021-08-26 14:33:02
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=(1<<14)+5,M=40050,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
int a[2][M];
char s[M];
int n,m,len;
int f[M],tot;
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
int id(int x,int y){return x*m+y;}
void merge(int u,int v){
	u=find(u),v=find(v);
	if(u!=v){
		f[v]=u;tot--;
	}
}
int main(){
	scanf("%d%d",&n,&m);len=m/4;
	int mm=m<<1;
	for(int i=1;i<=mm;i++) f[i]=i; 
	rep(i,1,n){
		scanf("%s",s+1);
		int u=i&1;
		rep(j,1,len){
			int x=isdigit(s[j])?s[j]-'0':s[j]-'A'+10;
			rep(k,1,4){
				int y=(j-1)*4+k;
				a[u][y]=(x>>(4-k))&1;
				f[id(u,y)]=id(u,y);
				tot+=(x>>(4-k))&1;
			}
		}
		rep(j,1,m){
			//注意顺序合并到左上.
			if(j<m&&a[u][j]&&a[u][j+1]) merge(id(u,j),id(u,j+1));
			if(a[u][j]&&a[u^1][j]) merge(id(u,j),id(u^1,j));
		}
	}
	printf("%d\n",tot);
	return 0;
}