#include <bits/stdc++.h> using namespace std; #define FOR(i, a, b) for(int i=a; i<=b; ++i) #define ll long long #define pi pair<int, int> #define f first #define s second #define eb emplace_back #define pb push_back #define sz(A) (int)(A.size()) const int maxn=2e3+3, p1=3251, p2=2027, mod=1e9+123, maxl=26; int pot1[maxl], pot2[maxl]; map<pi, vector<int>> kolumny, wiersze; pi klucze_wiersze[maxl], klucze_kolumny[maxl]; int board[maxn][maxn]; vector<pair<int, pi>> odp; int n, m; int main() { // cin.tie(0) -> ios_base::sync_with_stdio(0); pot1[0]=pot2[0]=1; FOR(i, 1, maxl-1) { pot1[i]=(1ll*pot1[i-1]*p1)%mod; pot2[i]=(1ll*pot2[i-1]*p2)%mod; } cin >> n >> m; string inp; FOR(i, 1, n) { cin >> inp; FOR(j, 1, m) { int x = inp[j-1]-'A'; board[i][j]=x; } } // hahsuj wiersze FOR(i, 1, n) { int h1=0; int h2=0; FOR(j, 1, m) { int x = board[i][j]; h1=(0ll+h1+pot1[x])%mod; h2=(0ll+h2+pot2[x])%mod; } wiersze[{h1, h2}].eb(i); } // hashuj kolumny FOR(j, 1, m) { int h1=0; int h2=0; FOR(i, 1, n) { int x = board[i][j]; h1=(0ll+h1+pot1[x])%mod; h2=(0ll+h2+pot2[x])%mod; } kolumny[{h1, h2}].eb(j); } // generuj klucze dla kazdego koloru FOR(i, 0, maxl-1) { klucze_wiersze[i]={(1ll*m*pot1[i])%mod, (1ll*m*pot2[i])%mod}; klucze_kolumny[i]={(1ll*n*pot1[i])%mod, (1ll*n*pot2[i])%mod}; } // cofaj ruchy od konca int kol_cnt=0, wier_cnt=0; vector<int> to_remove; while(wier_cnt<n && kol_cnt<m) { // cout << wier_cnt << ' ' << kol_cnt << '\n'; // probuj kolumny usuwac to_remove.clear(); FOR(i, 0, maxl-1) { pi klucz = klucze_kolumny[i]; FOR(j, 0, sz(kolumny[klucz])-1) { int idx = kolumny[klucz][j]; // usuwam idx swap(kolumny[klucz].back(), kolumny[klucz][j]); kolumny[klucz].pop_back(); to_remove.eb(i); // cout << "usuwam kolumne: " << idx << " o kolorze: " << i << '\n'; odp.pb({1, {idx, i}}); ++kol_cnt; } } // zaktualizuj klucze wierszy for(int kol : to_remove) { // cout << "usuwam kolor z wierszy: " << kol << '\n'; FOR(i, 0, maxl-1) { int a = klucze_wiersze[i].f; int b = klucze_wiersze[i].s; a=(0ll+a+mod-pot1[i]+pot1[kol])%mod; b=(0ll+b+mod-pot2[i]+pot2[kol])%mod; klucze_wiersze[i] = {a, b}; } } // probuj wiersze usuwac to_remove.clear(); FOR(i, 0, maxl-1) { pi klucz = klucze_wiersze[i]; FOR(j, 0, sz(wiersze[klucz])-1) { int idx = wiersze[klucz][j]; // usuwam idx swap(wiersze[klucz].back(), wiersze[klucz][j]); wiersze[klucz].pop_back(); to_remove.eb(i); // cout << "usuwam wiersz: " << idx << " o kolorze: " << i << '\n'; odp.pb({2, {idx, i}}); ++wier_cnt; } } // zaktualizuj klucze kolumn for(int kol : to_remove) { // cout << "usuwam kolor z kolumn: " << kol << '\n'; FOR(i, 0, maxl-1) { int a = klucze_kolumny[i].f; int b = klucze_kolumny[i].s; a=(0ll+a+mod-pot1[i]+pot1[kol])%mod; b=(0ll+b+mod-pot2[i]+pot2[kol])%mod; klucze_kolumny[i] = {a, b}; } } } reverse(odp.begin(), odp.end()); cout << sz(odp) << '\n'; for(auto &[a, b] : odp) { if(a==1) cout << "K "; else cout << "R "; cout << b.f << ' ' << (char)(b.s+'A') << '\n'; } }
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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | #include <bits/stdc++.h> using namespace std; #define FOR(i, a, b) for(int i=a; i<=b; ++i) #define ll long long #define pi pair<int, int> #define f first #define s second #define eb emplace_back #define pb push_back #define sz(A) (int)(A.size()) const int maxn=2e3+3, p1=3251, p2=2027, mod=1e9+123, maxl=26; int pot1[maxl], pot2[maxl]; map<pi, vector<int>> kolumny, wiersze; pi klucze_wiersze[maxl], klucze_kolumny[maxl]; int board[maxn][maxn]; vector<pair<int, pi>> odp; int n, m; int main() { // cin.tie(0) -> ios_base::sync_with_stdio(0); pot1[0]=pot2[0]=1; FOR(i, 1, maxl-1) { pot1[i]=(1ll*pot1[i-1]*p1)%mod; pot2[i]=(1ll*pot2[i-1]*p2)%mod; } cin >> n >> m; string inp; FOR(i, 1, n) { cin >> inp; FOR(j, 1, m) { int x = inp[j-1]-'A'; board[i][j]=x; } } // hahsuj wiersze FOR(i, 1, n) { int h1=0; int h2=0; FOR(j, 1, m) { int x = board[i][j]; h1=(0ll+h1+pot1[x])%mod; h2=(0ll+h2+pot2[x])%mod; } wiersze[{h1, h2}].eb(i); } // hashuj kolumny FOR(j, 1, m) { int h1=0; int h2=0; FOR(i, 1, n) { int x = board[i][j]; h1=(0ll+h1+pot1[x])%mod; h2=(0ll+h2+pot2[x])%mod; } kolumny[{h1, h2}].eb(j); } // generuj klucze dla kazdego koloru FOR(i, 0, maxl-1) { klucze_wiersze[i]={(1ll*m*pot1[i])%mod, (1ll*m*pot2[i])%mod}; klucze_kolumny[i]={(1ll*n*pot1[i])%mod, (1ll*n*pot2[i])%mod}; } // cofaj ruchy od konca int kol_cnt=0, wier_cnt=0; vector<int> to_remove; while(wier_cnt<n && kol_cnt<m) { // cout << wier_cnt << ' ' << kol_cnt << '\n'; // probuj kolumny usuwac to_remove.clear(); FOR(i, 0, maxl-1) { pi klucz = klucze_kolumny[i]; FOR(j, 0, sz(kolumny[klucz])-1) { int idx = kolumny[klucz][j]; // usuwam idx swap(kolumny[klucz].back(), kolumny[klucz][j]); kolumny[klucz].pop_back(); to_remove.eb(i); // cout << "usuwam kolumne: " << idx << " o kolorze: " << i << '\n'; odp.pb({1, {idx, i}}); ++kol_cnt; } } // zaktualizuj klucze wierszy for(int kol : to_remove) { // cout << "usuwam kolor z wierszy: " << kol << '\n'; FOR(i, 0, maxl-1) { int a = klucze_wiersze[i].f; int b = klucze_wiersze[i].s; a=(0ll+a+mod-pot1[i]+pot1[kol])%mod; b=(0ll+b+mod-pot2[i]+pot2[kol])%mod; klucze_wiersze[i] = {a, b}; } } // probuj wiersze usuwac to_remove.clear(); FOR(i, 0, maxl-1) { pi klucz = klucze_wiersze[i]; FOR(j, 0, sz(wiersze[klucz])-1) { int idx = wiersze[klucz][j]; // usuwam idx swap(wiersze[klucz].back(), wiersze[klucz][j]); wiersze[klucz].pop_back(); to_remove.eb(i); // cout << "usuwam wiersz: " << idx << " o kolorze: " << i << '\n'; odp.pb({2, {idx, i}}); ++wier_cnt; } } // zaktualizuj klucze kolumn for(int kol : to_remove) { // cout << "usuwam kolor z kolumn: " << kol << '\n'; FOR(i, 0, maxl-1) { int a = klucze_kolumny[i].f; int b = klucze_kolumny[i].s; a=(0ll+a+mod-pot1[i]+pot1[kol])%mod; b=(0ll+b+mod-pot2[i]+pot2[kol])%mod; klucze_kolumny[i] = {a, b}; } } } reverse(odp.begin(), odp.end()); cout << sz(odp) << '\n'; for(auto &[a, b] : odp) { if(a==1) cout << "K "; else cout << "R "; cout << b.f << ' ' << (char)(b.s+'A') << '\n'; } } |