#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC target(sse, sse2, sse3, popcnt, tune = native)
using namespace std;
const long long MAXN = 1e5 + 47, inf = 1e9 + 47;
long long n, m, k;
vector<vector<long long> > dp, pref;
struct node {
  long long l, r, mx, dw;
  node() {
    l = r = mx = -1;
    dw = inf;
  }
};
vector<node> t(4 * MAXN);
void build(long long i, long long l, long long r, vector<long long> &a) {
  t[i].l = l, t[i].r = r, t[i].dw = inf;
  if (l == r) {
    t[i].mx = a[l];
    return;
  }
  long long mid = (l + r) / 2;
  build(i * 2, l, mid, a);
  build(i * 2 + 1, mid + 1, r, a);
  t[i].mx = max(t[i * 2].mx, t[i * 2 + 1].mx);
}
void push(long long i) {
  if (t[i].dw == inf) return;
  t[i].mx += t[i].dw;
  if (t[i].l != t[i].r) {
    if (t[i * 2].dw == inf) t[i * 2].dw = 0;
    if (t[i * 2 + 1].dw == inf) t[i * 2 + 1].dw = 0;
    t[i * 2].dw += t[i].dw;
    t[i * 2 + 1].dw += t[i].dw;
  }
  t[i].dw = inf;
}
void update(long long i, long long l, long long r, long long add) {
  push(i);
  if (t[i].l > r || l > t[i].r) return;
  if (l <= t[i].l && t[i].r <= r) {
    if (t[i].dw == inf) t[i].dw = 0;
    t[i].dw += add;
    push(i);
    return;
  }
  update(i * 2, l, r, add);
  update(i * 2 + 1, l, r, add);
  t[i].mx = max(t[i * 2].mx, t[i * 2 + 1].mx);
}
long long get_max() {
  push(1);
  return t[1].mx;
}
vector<vector<long long> > izn;
void read() {
  cin >> n >> m >> k;
  n++;
  dp.resize(n, vector<long long>(m - k + 1, 0));
  pref.resize(n, vector<long long>(m, 0));
  izn.resize(n, vector<long long>(m, 0));
  for (long long i = 0; i < n - 1; ++i)
    for (long long j = 0; j < m; ++j) cin >> pref[i][j];
  izn = pref;
  for (long long a = 0; a < n; ++a) {
    vector<long long> t(m, 0);
    for (long long b = 0; b < m; ++b) {
      t[b] += pref[a][b];
      if (b != 0) t[b] += t[b - 1];
      pref[a][b] = t[b];
      if (a != 0) pref[a][b] += pref[a - 1][b];
    }
  }
}
long long seif(long long a, long long b) {
  if (a < 0 || b < 0) return 0;
  return pref[a][b];
}
long long get(long long deep, long long lvl, long long l, long long r) {
  if (deep == 1) {
    long long res = pref[lvl][r];
    res -= seif(lvl, l - 1);
    return res;
  }
  return pref[lvl][r] + seif(lvl - 2, l - 1) - seif(lvl, l - 1) -
         seif(lvl - 2, r);
}
void print(long long i) {
  push(i);
  if (t[i].l == t[i].r) {
    cout << t[i].mx << " ";
  } else
    print(i * 2), print(i * 2 + 1);
}
void solve() {
  for (long long l = 0; l < m; ++l) {
    long long r = l + k - 1;
    if (l >= (long long)dp[0].size()) break;
    dp[0][l] = 0;
    dp[1][l] = get(2, 1, l, r);
  }
  for (long long lvl = 2; lvl < n; ++lvl) {
    build(1, 0, (long long)dp[lvl].size() - 1, dp[lvl - 1]);
    for (long long p = 0; p < k; ++p) {
      long long l = max(0LL, p - k + 1),
                r = min((long long)dp[lvl].size() - 1, p);
      update(1, l, r, -izn[lvl - 1][p]);
    }
    dp[lvl][0] = get_max() + get(2, lvl, 0, k - 1);
    long long l = 1, r = k;
    while (r < m) {
      long long l1 = max(0LL, r - k + 1),
                r1 = min((long long)dp[lvl].size() - 1, r);
      update(1, l1, r1, -izn[lvl - 1][r]);
      l1 = max(0LL, l - k), r1 = min((long long)dp[lvl].size() - 1, l - 1);
      update(1, l1, r1, izn[lvl - 1][l - 1]);
      dp[lvl][l] = get_max() + get(2, lvl, l, r);
      l++, r++;
    }
  }
  long long ans = 0;
  for (long long a = 0; a < n; ++a) {
    for (long long b = 0; b < m - k + 1; ++b) ans = max(ans, dp[a][b]);
  }
  cout << ans << endl;
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  long long t = 1;
  while (t--) {
    read();
    solve();
  }
}
