#include <bits/stdc++.h>
using namespace std;
const int maxn = 1002;
const int INF = 1000 * 1000 * 1000 + 97;
struct Rect {
  int x, y;
  long long musor;
  Rect(int xx, int yy, long long mus) {
    x = xx;
    y = yy;
    musor = mus;
  }
  friend inline bool operator<(const Rect& a, const Rect& b) {
    if (a.musor != b.musor) return a.musor < b.musor;
    if (a.y != b.y) return a.y < b.y;
    return a.x < b.x;
  }
};
int n, m, a, b;
struct RMQ {
  int count;
  int shift;
  vector<int> mins;
  RMQ() { construct(maxn); }
  RMQ(int c) { construct(c); }
  void construct(int c) {
    count = c;
    shift = 1;
    while (shift < c) shift *= 2;
    mins.assign(2 * shift + 1, INF);
  }
  void setValue(int index, int value) {
    index += shift;
    mins[index] = value;
    while (index > 1)
      index /= 2, mins[index] = min(mins[2 * index], mins[2 * index + 1]);
  }
  int getMin(int l, int r) {
    l += shift;
    r += shift;
    int minimum = INF;
    while (l < r) {
      minimum = min(minimum, min(mins[l], mins[r - 1]));
      l = (l + 1) / 2;
      r /= 2;
    }
    return minimum;
  }
};
int hs[maxn][maxn];
long long ss[maxn][maxn];
RMQ fieldMins[maxn];
bool used[maxn][maxn];
vector<Rect> rs;
vector<Rect> answer;
int main() {
  cin >> n >> m >> a >> b;
  for (int yy = 0; yy < n; yy++)
    for (int xx = 0; xx < m; xx++) {
      scanf("%d", &hs[yy][xx]);
      ss[yy + 1][xx + 1] =
          hs[yy][xx] + ss[yy + 1][xx] + ss[yy][xx + 1] - ss[yy][xx];
    }
  for (int xx = 0; xx < m; xx++) {
    RMQ tempRmq(n);
    for (int yy = 0; yy < n; yy++) tempRmq.setValue(yy, hs[yy][xx]);
    for (int yy = 0; yy + a <= n; yy++)
      fieldMins[yy].setValue(xx, tempRmq.getMin(yy, yy + a));
  }
  rs.reserve((n - a + 1) * (m - b + 1));
  for (int yy = 0; yy <= n - a; yy++)
    for (int xx = 0; xx <= m - b; xx++) {
      long long baseMusor =
          ss[yy + a][xx + b] - ss[yy + a][xx] - ss[yy][xx + b] + ss[yy][xx];
      baseMusor -=
          fieldMins[yy].getMin(xx, xx + b) * (long long)a * (long long)b;
      rs.push_back(Rect(xx, yy, baseMusor));
    }
  sort(rs.begin(), rs.end());
  int maxAnswerCount = (n / a + 1) * (m / b + 1);
  answer.reserve(maxAnswerCount);
  for (int i = 0; i < rs.size(); i++) {
    Rect r = rs[i];
    if (used[r.y][r.x] || used[r.y + a - 1][r.x] || used[r.y][r.x + b - 1] ||
        used[r.y + a - 1][r.x + b - 1])
      continue;
    for (int yy = r.y; yy < r.y + a; yy++)
      for (int xx = r.x; xx < r.x + b; xx++) used[yy][xx] = true;
    answer.push_back(r);
    if (answer.size() >= maxAnswerCount) break;
  }
  cout << answer.size() << endl;
  for (int i = 0; i < answer.size(); i++)
    printf("%d %d %lld\n", answer[i].y + 1, answer[i].x + 1, answer[i].musor);
  return 0;
}
