#if defined(EMBE_DEBUG) && !defined(NDEBUG)
#include "embe-debug.hpp"
#else
#define LOG_INDENT(...) do {} while (false)
#define LOG(...) do {} while (false)
#define DUMP(...) do {} while (false)
#endif
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <ranges>
#include <string>
#include <tuple>
#include <vector>
using namespace std;
namespace {
vector<tuple<char, int, char>> solve(vector<string> const& target)
{
vector<tuple<char, int, char>> res;
int n = target.size();
int m = target[0].size();
vector<int> rows;
ranges::copy(views::iota(0, n), back_inserter(rows));
vector<int> cols;
ranges::copy(views::iota(0, m), back_inserter(cols));
auto row_colors = vector(26, vector(n, 0));
auto col_colors = vector(26, vector(m, 0));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int c = target[i][j] - 'A';
++row_colors[c][i];
++col_colors[c][j];
}
}
vector<int> new_rows;
new_rows.reserve(n);
vector<int> new_cols;
new_cols.reserve(m);
while (!rows.empty() && !cols.empty()) {
new_rows.clear();
for (int i: rows) {
bool found = false;
for (int c = 0; c < 26; ++c) {
if (row_colors[c][i] == int(cols.size())) {
res.emplace_back('R', i + 1, 'A' + c);
for (int j: cols) {
--col_colors[target[i][j] - 'A'][j];
}
found = true;
break;
}
}
if (!found) {
new_rows.push_back(i);
}
}
swap(new_rows, rows);
if (rows.empty()) break;
new_cols.clear();
for (int j: cols) {
bool found = false;
for (int c = 0; c < 26; ++c) {
if (col_colors[c][j] == int(rows.size())) {
res.emplace_back('K', j + 1, 'A' + c);
for (int i: rows) {
--row_colors[target[i][j] - 'A'][i];
}
found = true;
break;
}
}
if (!found) {
new_cols.push_back(j);
}
}
swap(new_cols, cols);
}
ranges::reverse(res);
return res;
}
}
int main()
{
iostream::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<string> target(n);
for (auto& s: target) {
cin >> s;
assert(int(s.size()) == m);
}
auto res = solve(target);
cout << res.size() << '\n';
for (auto [op, x, c]: res) {
cout << op << ' ' << x << ' ' << c << '\n';
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | #if defined(EMBE_DEBUG) && !defined(NDEBUG) #include "embe-debug.hpp" #else #define LOG_INDENT(...) do {} while (false) #define LOG(...) do {} while (false) #define DUMP(...) do {} while (false) #endif #include <algorithm> #include <cassert> #include <iostream> #include <iterator> #include <ranges> #include <string> #include <tuple> #include <vector> using namespace std; namespace { vector<tuple<char, int, char>> solve(vector<string> const& target) { vector<tuple<char, int, char>> res; int n = target.size(); int m = target[0].size(); vector<int> rows; ranges::copy(views::iota(0, n), back_inserter(rows)); vector<int> cols; ranges::copy(views::iota(0, m), back_inserter(cols)); auto row_colors = vector(26, vector(n, 0)); auto col_colors = vector(26, vector(m, 0)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { int c = target[i][j] - 'A'; ++row_colors[c][i]; ++col_colors[c][j]; } } vector<int> new_rows; new_rows.reserve(n); vector<int> new_cols; new_cols.reserve(m); while (!rows.empty() && !cols.empty()) { new_rows.clear(); for (int i: rows) { bool found = false; for (int c = 0; c < 26; ++c) { if (row_colors[c][i] == int(cols.size())) { res.emplace_back('R', i + 1, 'A' + c); for (int j: cols) { --col_colors[target[i][j] - 'A'][j]; } found = true; break; } } if (!found) { new_rows.push_back(i); } } swap(new_rows, rows); if (rows.empty()) break; new_cols.clear(); for (int j: cols) { bool found = false; for (int c = 0; c < 26; ++c) { if (col_colors[c][j] == int(rows.size())) { res.emplace_back('K', j + 1, 'A' + c); for (int i: rows) { --row_colors[target[i][j] - 'A'][i]; } found = true; break; } } if (!found) { new_cols.push_back(j); } } swap(new_cols, cols); } ranges::reverse(res); return res; } } int main() { iostream::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<string> target(n); for (auto& s: target) { cin >> s; assert(int(s.size()) == m); } auto res = solve(target); cout << res.size() << '\n'; for (auto [op, x, c]: res) { cout << op << ' ' << x << ' ' << c << '\n'; } return 0; } |
English