比赛链接:

https://codeforces.com/contest/1638

C. Inversion Graph

题目大意:

给一个排列 \(p\),当 \(i < j\) 并且 \(p_i\) > \(p_j\) 时,会有一条边将这两个点相连,判断该排列中有多少个连通分量。

思路:

我们可以将排列分成两个集合 \(a\)\(b\),当前面集合中的点的最大值比后面集合的最小值还要小的时候,说明前面两个集合之间有边,反之,说明出现一个新的连通分量了。

代码:

#include <bits/stdc++.h>
using namespace std;
#define IOS() ios_base::sync_with_stdio(false);cin.tie(0);
void solve(){
	int n, ans = 1;
	cin >> n;
	vector <int> a(n), b(n);
	for (int i = 0; i < n; ++ i){
		cin >> a[i];
		b[i] = a[i];
	}
	for (int i = 1; i < n; ++ i)
		a[i] = max(a[i - 1], a[i]);
	for (int i = n - 2; i >= 0; -- i)
		b[i] = min(b[i], b[i + 1]);
	for (int i = 0; i < n - 1; ++ i)
		if (a[i] < b[i + 1])
			ans++;
	cout << ans << "\n";
}
int main(){
	IOS();
	int T;
	cin >> T;
	while (T--)
		solve();
	return 0;
}

D. Big Brush

题目大意:

\(n * m\) 的矩阵,每个格子有一个颜色,有一个刷子,每刷一次可以让 \((x, y), (x + 1, y), (x, y + 1), (x + 1, y + 1)\) 变成一个颜色,问用不超过 \(n * m\) 步操作能不能刷出给出的矩阵,若能,输出刷的步骤,不能输出 -1。

思路:

反过来思考,通过 \(bfs\) 反向操作即可。最后一步刷的一定会形成一个 2 * 2 的颜色一样的矩阵,然后将这个矩阵标记一下,去找周围的前一步的操作,总共有八种情况。
每一次标记就是将操作的这一步的矩阵的全部元素改成 0,表示这个格子是特殊格子,不管是什么颜色都没有关系,因为后面一步的操作会将它覆盖掉。

代码:

#include <bits/stdc++.h>
using namespace std;
#define PII pair <int, int>
#define fi first
#define se second
const int N = 1e3 + 10;
int n, m, a[N][N];
vector < array <int, 3> > ans;
queue < PII > q;
int color(int x, int y){
	for (int dx = 0; dx <= 1; dx ++ )
		for (int dy = 0; dy <= 1; dy ++ )
			if (a[x + dx][y + dy] != 0)
				return a[x + dx][y + dy];
	return 0;
}
bool judge(int x, int y){
	if (x < 1 || x >= n || y < 1 || y >= m) return false;
	int c = color(x, y);
	for (int dx = 0; dx <= 1; dx ++ )
		for (int dy = 0; dy <= 1; dy ++ )
			if (a[x + dx][y + dy] != 0 && a[x + dx][y + dy] != c)
				return false;
	return true;
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0); 
	cin >> n >> m;
	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= m; j ++ )
			cin >> a[i][j];
	for (int i = 1; i < n; i ++ )
		for (int j = 1; j < m; j ++ )
			if ( judge(i, j) )
				q.push( {i, j} );
	while ( q.size() ){
		PII t = q.front();
		q.pop();
		int x = t.fi, y = t.se;
		if ( !color(x, y) ) continue;
		ans.push_back( {x, y, color(x, y) } );
		for (int dx = 0; dx <= 1; dx ++ )
			for (int dy = 0; dy <= 1; dy ++ )
				a[x + dx][y + dy] = 0;
		for (int dx = -1; dx <= 1; dx ++ )
			for (int dy = -1; dy <= 1; dy ++ ){
				if (dx == 0 && dy == 0) continue;
				if ( judge(x + dx, y + dy) ) q.push({x + dx, y + dy});
			}
	}
	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= n; j ++ )
			if (a[i][j]){
				cout << "-1\n";
				return 0;
			}
	reverse( ans.begin(), ans.end() );
	cout << ans.size() << "\n";
	for (auto [x, y, w] : ans)
		cout << x << " " << y << " " << w << "\n";
	return 0;
}
posted on 2022-03-07 20:38  Hamine  阅读(39)  评论(0编辑  收藏  举报