#include <bits/stdc++.h>
using namespace ::std;
const long double PI = acos(-1);
const long long MOD = 1000000000 + 7;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
long long add(long long a, long long b, long long m = MOD) {
  if (a >= m) a %= m;
  if (b >= m) b %= m;
  if (a < 0) a += m;
  if (b < 0) b += m;
  long long res = a + b;
  if (res >= m or res <= -m) res %= m;
  if (res < 0) res += m;
  return res;
}
long long mul(long long a, long long b, long long m = MOD) {
  if (a >= m) a %= m;
  if (b >= m) b %= m;
  if (a < 0) a += m;
  if (b < 0) b += m;
  long long res = a * b;
  if (res >= m or res <= -m) res %= m;
  if (res < 0) res += m;
  return res;
}
long long pow_mod(long long a, long long b, long long m = MOD) {
  long long res = 1LL;
  a = a % m;
  while (b) {
    if (b & 1) res = mul(res, a, m);
    b >>= 1;
    a = mul(a, a, m);
  }
  return res;
}
long long fastexp(long long a, long long b) {
  long long res = 1LL;
  while (b) {
    if (b & 1) res = res * a;
    b >>= 1;
    a *= a;
  }
  return res;
}
int gcdExtendido(int a, int b, int *x, int *y) {
  if (a == 0) {
    *x = 0;
    *y = 1;
    return b;
  }
  int x1, y1;
  int gcd = gcdExtendido(b % a, a, &x1, &y1);
  *x = y1 - (b / a) * x1;
  *y = x1;
  return gcd;
}
int modInverso(int a, int m) {
  int x, y;
  int g = gcdExtendido(a, m, &x, &y);
  if (g != 1)
    return -1;
  else
    return (x % m + m) % m;
}
const int N = 1000 + 2;
const int LOG = 11;
int n, m;
int l1, l2;
int a[N][N];
long long sum[N][N];
int ST[N][LOG];
bool vis[N][N];
long long query(int f1, int c1, int f2, int c2) {
  return sum[f2][c2] + sum[f1 - 1][c1 - 1] - sum[f1 - 1][c2] - sum[f2][c1 - 1];
}
void computeRow(int r) {
  for (int i = 1; i <= m; i++) {
    ST[i][0] = a[r][i];
  }
  for (int d = 1; 1 << d <= m; d++) {
    int dis = 1 << (d - 1);
    for (int i = 1; i + 2 * dis - 1 <= m; i++) {
      ST[i][d] = min(ST[i][d - 1], ST[i + dis][d - 1]);
    }
  }
  int k = 31 - __builtin_clz(l2);
  int dis = 1 << k;
  for (int i = 1; i + l2 - 1 <= m; i++) {
    a[r][i] = min(ST[i][k], ST[i + l2 - dis][k]);
  }
}
void computeCol(int c) {
  for (int i = 1; i <= n; i++) {
    ST[i][0] = a[i][c];
  }
  for (int d = 1; 1 << d <= n; d++) {
    int dis = 1 << (d - 1);
    for (int i = 1; i + 2 * dis - 1 <= n; i++) {
      ST[i][d] = min(ST[i][d - 1], ST[i + dis][d - 1]);
    }
  }
  int k = 31 - __builtin_clz(l1);
  int dis = 1 << k;
  for (int i = 1; i + l1 - 1 <= n; i++) {
    a[i][c] = min(ST[i][k], ST[i + l1 - dis][k]);
  }
}
void update(int x, int y) {
  for (int i = max(1, x - l1 + 1); i <= x + l1 - 1; i++) {
    for (int j = max(1, y - l2 + 1); j <= y + l2 - 1; j++) {
      vis[i][j] = true;
    }
  }
}
int main() {
  scanf("%d %d", &(n), &(m));
  scanf("%d %d", &(l1), &(l2));
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      scanf("%d", &(a[i][j]));
      sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
    }
  }
  for (int i = 1; i <= n; i++) {
    computeRow(i);
  }
  for (int i = 1; i <= m; i++) {
    computeCol(i);
  }
  vector<pair<long long, pair<int, int> > > rects, ans;
  for (int i = 1; i + l1 - 1 <= n; i++) {
    for (int j = 1; j + l2 - 1 <= m; j++) {
      long long val =
          query(i, j, i + l1 - 1, j + l2 - 1) - 1LL * l1 * l2 * a[i][j];
      rects.emplace_back(make_pair(val, make_pair(i, j)));
    }
  }
  sort((rects).begin(), (rects).end());
  for (auto e : rects) {
    if (vis[e.second.first][e.second.second]) continue;
    ans.emplace_back(e);
    update(e.second.first, e.second.second);
  }
  printf("%d\n", (int)ans.size());
  for (auto e : ans) {
    printf("%d %d %lld\n", e.second.first, e.second.second, e.first);
  }
  return 0;
}
