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
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int base = 2048;

struct SegmentTree {
	vector<char>T;
	SegmentTree() {
		T = vector<char>(2 * base);
	}

	void add(int v, char x) {
		v += base;
		T[v] = x;
		v /= 2;

		while (v) {
			T[v] = !T[2 * v] ? T[2 * v + 1] : 
				!T[2 * v + 1] ? T[2 * v] : 
				T[2 * v] == T[2 * v + 1] ? T[2 * v] : 1;
			v /= 2;
		}
	}

	bool isFull() {
		return T[1] != 1;
	}
};

vector<SegmentTree>Wiersze(base);
vector<SegmentTree>Kolumny(base);

struct Kolor {
	char a;
	int b;
	char c;
};

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int n, m; cin >> n >> m;
	vector<vector<char>>G(n, vector<char>(m, 0));
	for (int i = 0; i < n; i++) {
		string s; cin >> s;
		for (int j = 0; j < m; j++) {
			Wiersze[i].add(j, s[j]);
			Kolumny[j].add(i, s[j]);
		}
	}

	vector<Kolor>result;
	for (int C = 0; C < n + m; C++) {
		for (int i = 0; i < n; i++) {
			if (Wiersze[i].isFull() && Wiersze[i].T[1] != 0) {
				result.push_back({ 'R', i + 1, Wiersze[i].T[1] });
				Wiersze[i].T[1] = 0;
				for (int j = 0; j < m; j++) {
					if (Kolumny[j].T[1]) Kolumny[j].add(i, 0);
				}
			}
		}

		for (int i = 0; i < m; i++) {
			if (Kolumny[i].isFull() && Kolumny[i].T[1] != 0) {
				result.push_back({ 'K', i + 1, Kolumny[i].T[1] });
				Kolumny[i].T[1] = 0;
				for (int j = 0; j < n; j++) {
					if (Wiersze[j].T[1]) Wiersze[j].add(i, 0);
				}
			}
		}
	}

	cout << result.size() << '\n';
	reverse(result.begin(), result.end());
	for (auto p : result) cout << p.a << " " << p.b << " " << p.c << '\n';

	return 0;
}