#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <locale>
#include <iostream>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

using ll = long long;
using ld = long double;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template <typename T> int len(const T &x) { return x.size(); }

template<typename T>
vector<T> table(int n, T v) { return vector<T>(n, v); }

template <class... Args>
auto table(int n, Args... args) {
  auto val = table(args...);
  return vector<decltype(val)>(n, move(val));
}

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

template <typename T>
class StarrySkyTree {
  const int n;
  vector<T> data, lazy;
  void add_sub(int l, int r, int node, int lb, int ub, T val) {
    if (ub <= l || r <= lb) return;
    if (l <= lb && ub <= r) { lazy[node] += val; return; }
    int left = node * 2, right = left + 1;
    add_sub(l, r, left, lb, (lb + ub) / 2, val);
    add_sub(l, r, right, (lb + ub) / 2, ub, val);
    data[node] = min(data[left] + lazy[left], data[right] + lazy[right]);
  }
  T min_sub(int l, int r, int node, int lb, int ub) const {
    if (ub <= l || r <= lb) return 1e18;
    if (l <= lb && ub <= r) return data[node] + lazy[node];
    T vl = min_sub(l, r, node * 2 + 0, lb, (lb + ub) / 2);
    T vr = min_sub(l, r, node * 2 + 1, (lb + ub) / 2, ub);
    return lazy[node] + min(vl, vr);
  }
  int size(int n) {
    return n == 1 ? n : size((n + 1) / 2) * 2;
  }
public:
  StarrySkyTree(int m) : n(size(m)), data(n * 2, 0), lazy(n * 2, 0) {}
  void add(int l, int r, T val) { add_sub(l, r, 1, 0, n, val); }
  T minimum(int l, int r) const { return min_sub(l, r, 1, 0, n); }
};

vector<pair<int,ll>> vec[256];

void solve(ll N, ll M, vector<ll> A, vector<vector<ll>> B) {
  // int len = 0;
  StarrySkyTree<ll> sky(N);
  ll res = 0;
  REP(i,N) {
    // if (i > 0) len += A[i-1];
    ll sum = 0;
    REP(j,M) {
      int en = i;
      while (!vec[j].empty() && vec[j].back().second < B[i][j]) {
        sky.add(vec[j].back().first, en, -(B[i][j] - vec[j].back().second));
        en = vec[j].back().first;
        vec[j].pop_back();
      }
      vec[j].emplace_back(en, B[i][j]);
      sum += B[i][j];
    }
    sky.add(i, i + 1, -sum);
    if (i > 0) sky.add(0, i, A[i-1]);
    res = max(res, -sky.minimum(0, i + 1));
  }
  cout << res << endl;
}

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha << setprecision(12) << fixed;
  cout.imbue(loc);
	ll M;
	ll N;
	scanf("%lld", &N);
	vector<ll> A((N-1)-1+1);
	scanf("%lld", &M);
	vector<vector<ll>> B(N-1+1,vector<ll>(M-1+1));
	for (int i = 0 ; i <= (N-1)-1 ; i++) {
	  scanf("%lld", &A[i]);
	}
	for (int i = 0 ; i <= N-1 ; i++) {
	  for (int j = 0 ; j <= M-1 ; j++) {
	    scanf("%lld", &B[i][j]);
	  }
	}
	solve(N, M, A, B);
	return 0;
}


Measured memory_bytes: 16768