专栏文章

题解:P14299 [JOI2023 预选赛 R2] 填充 / Painting

P14299题解参与者 3已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@minh1o65
此快照首次捕获于
2025/12/02 02:17
3 个月前
此快照最后确认于
2025/12/02 02:17
3 个月前
查看原文
这哪是好题了。不是一个很水的搜索吗。

solve\texttt{solve}

首先我们开一个 n×mn\times m 的并查集,按顺序给矩阵标号,第 ii 行第 jj 个即为 (i1)×m+j(i-1)\times m+j
然后把相邻颜色相同的全部合并,统计一下每个联通块的大小和颜色。
然后对每个联通块进行搜索,把相邻的联通块编号塞进一个 set,退出搜索后枚举哪个联通块最大。此时把该联通块的颜色改成这个最大联通块的颜色,所得答案就是这个联通块的最优解。
用一个变量 ansans 依次比较记录最大答案即可。

code\texttt{code}

CPP
#include <bits/stdc++.h>
#define int long long
#define lint long long
#define endl '\n'
using namespace std;
const int N = 5e2+5;
const int dx[4] = {1,0,-1,0};
const int dy[4] = {0,1,0,-1};

struct node{
	int num;
	int col;
}a[N][N];

int n,m,f[N*N];
int sz[N*N],col[N*N];
bitset<1> vis[N][N];
set<int > s;
map<int,int > table;

inline int find(int x){
	if(f[x] == x) return x;
	return f[x] = find(f[x]);
}

inline void merge(int x,int y){
	int fx = find(x);
	int fy = find(y);
	if(fx != fy) f[fx] = fy;
}

inline void dfs(int x,int y){
	vis[x][y].set();
	for(int idx = 0; idx < 4; idx++){
		int tx = x + dx[idx];
		int ty = y + dy[idx];
		if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
		if(a[tx][ty].col == a[x][y].col && vis[tx][ty] == false) dfs(tx,ty);
		else if(a[tx][ty].col != a[x][y].col) s.insert(f[a[tx][ty].num]);
	}
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			cin >> a[i][j].col;
			a[i][j].num = (i-1) * m + j;
			f[a[i][j].num] = a[i][j].num;
			if(i > 1 && a[i-1][j].col == a[i][j].col) merge(a[i][j].num,a[i-1][j].num);
			if(j > 1 && a[i][j-1].col == a[i][j].col) merge(a[i][j].num,a[i][j-1].num);
		}
	}

	int ans = 0;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			sz[find(a[i][j].num)]++;
			col[f[a[i][j].num]] = a[i][j].col;
			ans = max(ans,sz[f[a[i][j].num]]);
		}
	}

	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			if(vis[i][j] == true)
				continue;

			dfs(i,j);

			for(int val : s){
				if(table.find(col[val]) == table.end())
					table[col[val]] = sz[val];
				else table[col[val]] += sz[val];
			}

			int maxCol = 0;
			for(auto val : table)
				if(!maxCol || table[maxCol] < val.second)
					maxCol = val.first;
			ans = max(ans,sz[f[a[i][j].num]]+table[maxCol]);
			s.clear(),table.clear();
		}
	}

	cout << ans << endl;
	return 0;
}

评论

2 条评论,欢迎与作者交流。

正在加载评论...