OIer的题解:P14197 [ICPC 2024 Hangzhou R] Kind of Bingo
greatest_show · · 题解
翻译
有一个
给定一个长度为 bingo 整数。
你可以对这个排列进行至多 bingo 整数。
思考
首先得明确问题核心:通过最多 bingo 整数 尽可能小。首先要理清两个关键对应 —— 一是根据单元格编号
没交换 bingo 整数 就是所有行“位”最大值里的最小值,选最早全满的行就行。有交换的话,核心是用排列里“标记早”的小“位”值,替换目标行里“标记晚”的大“位”值,减小该行的“位”最大值。最多能换 bingo 整数
Code:
#include <bits/stdc++.h>
using namespace std;
//greatest_show 水印
int n, m, k, t;
int p[114514];
int r[114514];
int a[114514];
int greatest_show() {
int b = 2e9; // 最小bingo值
for (int i = 1; i <= n; i++) {// 收集行位置
for (int j = 1; j <= m; j++) {
int c = i * m + j; // 单元格编号
r[j - 1] = p[c];
}
sort(r, r + m);
int s = min(k, m);
int b1; // 行最大位置
if (s == 0) {
b1 = r[m - 1];
} else {
int p1 = 0;
if (m > s) {
p1 = r[m - s - 1];
}
int p2 = a[s - 1];
if (p1 > p2) {
b1 = p1;
} else {
b1 = p2;
}
}
if (b1 < b) {
b = b1;
}
}
printf("%d\n", b);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &n, &m, &k);
t = n * m;
for (int i = 1; i <= t; i++) {// 记录单元格位置
int c;
scanf("%d", &c);
p[c] = i;
}
for (int c = 1; c <= t; c++) {// 收集位置排序
a[c - 1] = p[c];
}
sort(a, a + t);
greatest_show();
}
return 0;//好习惯++
}