#include <bits/stdc++.h>
using namespace std;
long long s[2000][2000], dp[2000][2000];
long long tree[2000 << 2];
inline void pushUp(int rt) { tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]); }
void update(int x, long long val, int L, int R, int rt) {
  if (L == R)
    tree[rt] = val;
  else {
    int mid = (L + R) >> 1;
    if (x <= mid)
      update(x, val, L, mid, rt << 1);
    else
      update(x, val, mid + 1, R, rt << 1 | 1);
    pushUp(rt);
  }
}
long long query(int x, int y, int L, int R, int rt) {
  if (x <= L && R <= y) return tree[rt];
  int mid = (L + R) >> 1;
  long long ans = -10000000000000LL;
  if (x <= mid) ans = max(ans, query(x, y, L, mid, rt << 1));
  if (y > mid) ans = max(ans, query(x, y, mid + 1, R, rt << 1 | 1));
  return ans;
}
int main() {
  long long tmp;
  int n, m;
  int i, j;
  while (~scanf("%d%d", &n, &m)) {
    for (i = 0; i < n; i++) {
      for (j = 0; j < m; j++) {
        scanf("%I64d", &s[i][j]);
        s[i][j] += s[i][j - 1];
        dp[i][j] = -10000000000000LL;
      }
    }
    for (i = 0; i < m; i++) {
      dp[0][i] = s[0][i];
      update(i, dp[0][i], 0, m - 1, 1);
    }
    for (i = 1; i < n; i++) {
      if (i & 1) {
        for (j = 0; j < m - 1; j++) {
          tmp = query(j + 1, m - 1, 0, m - 1, 1) + s[i][j];
          dp[i][j] = max(dp[i][j], tmp);
        }
        for (j = 0; j < m; j++) update(j, dp[i][j], 0, m - 1, 1);
      } else {
        for (j = 1; j < m; j++) {
          tmp = query(0, j - 1, 0, m - 1, 1) + s[i][j];
          dp[i][j] = max(dp[i][j], tmp);
        }
        for (j = 0; j < m; j++) update(j, dp[i][j], 0, m - 1, 1);
      }
    }
    printf("%I64d\n", *max_element(dp[n - 1], dp[n - 1] + m));
  }
  return 0;
}
