#include <bits/stdc++.h>
using namespace std;
int dp[52][20009];
int tree[20004 * 4];
int lazy[20004 * 4];
void build(int node, int start, int endd, int i) {
  if (start == endd)
    tree[node] = dp[i][start], lazy[node] = 0;
  else {
    int mid = (start + endd) / 2;
    build(2 * node, start, mid, i);
    build(2 * node + 1, mid + 1, endd, i);
    tree[node] = max(tree[2 * node], tree[2 * node + 1]);
    lazy[node] = 0;
  }
}
void updateRange(int node, int start, int endd, int l, int r, int val) {
  if (lazy[node] != 0) {
    tree[node] += lazy[node];
    if (start != endd)
      lazy[node * 2] += lazy[node], lazy[node * 2 + 1] += lazy[node];
    lazy[node] = 0;
  }
  if (start > endd || start > r || endd < l) return;
  if (start >= l && endd <= r) {
    tree[node] += val;
    if (start != endd) lazy[node * 2] += val, lazy[node * 2 + 1] += val;
    return;
  }
  int mid = (start + endd) / 2;
  updateRange(node * 2, start, mid, l, r, val);
  updateRange(node * 2 + 1, mid + 1, endd, l, r, val);
  tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
int queryRange(int node, int start, int endd, int l, int r) {
  if (start > endd || start > r || endd < l) return 0;
  if (lazy[node] != 0) {
    tree[node] += lazy[node];
    if (start != endd)
      lazy[node * 2] += lazy[node], lazy[node * 2 + 1] += lazy[node];
    lazy[node] = 0;
  }
  if (start >= l && endd <= r) return tree[node];
  int mid = (start + endd) / 2;
  int p1 = queryRange(node * 2, start, mid, l, r);
  int p2 = queryRange(node * 2 + 1, mid + 1, endd, l, r);
  return max(p1, p2);
}
int a[60][20004];
int pref[60][20004];
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int n, m, k;
  cin >> n >> m >> k;
  k--;
  int i, j;
  int mx = 0;
  for (i = 0; i < n; i++)
    for (j = 0; j < m; j++) {
      cin >> a[i][j];
      if (j == 0)
        pref[i][j] = a[i][j];
      else
        pref[i][j] = a[i][j] + pref[i][j - 1];
    }
  for (j = 0; j < m; j++) {
    if (j + k == m) break;
    dp[0][j] =
        pref[0][j + k] - pref[0][j - 1] + pref[1][j + k] - pref[1][j - 1];
    mx = max(mx, dp[0][j]);
    updateRange(1, 0, m, j, j, dp[0][j]);
  }
  for (i = 1; i < n; i++) {
    for (j = 0; j <= k; j++) updateRange(1, 0, m, 0, j, -a[i][j]);
    for (j = 0; j < m; j++) {
      if (j + k == m) break;
      dp[i][j] = pref[i][j + k] - pref[i][j - 1] + pref[i + 1][j + k] -
                 pref[i + 1][j - 1] + queryRange(1, 0, m, 0, m),
      mx = max(mx, dp[i][j]);
      updateRange(1, 0, m, max(0, j - k), j, a[i][j]);
      if (j + k + 1 < m)
        updateRange(1, 0, m, j + 1, j + 1 + k, -a[i][j + k + 1]);
    }
    build(1, 0, m, i);
  }
  cout << mx << endl;
  return 0;
}
