#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; } |