use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use core::ops::Bound::Excluded;
use core::ops::Bound::Included;
use std::collections::BTreeSet;
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer
}
fn read_lines<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split(' ').map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
fn read_tabulate<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
macro_rules! define {
    () => {};
    ($($token:tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        define_iter!(iter, $($token)*);
    };
}
macro_rules! define_iter {
    ($iter:expr) =>{};
    ($iter:expr,) =>{};
    ($iter:expr, $id:ident:$t:tt $($tail:tt)*) => {
        let $id: $t = $iter.next().unwrap().parse().ok().expect("Can't Parse");
        define_iter!($iter, $($tail)*);
    };
    ($iter:expr, mut $id:ident:$t:tt $($tail:tt)*) => {
        let mut $id: $t = $iter.next().unwrap().parse().ok().expect("Can't Parse");
        define_iter!($iter, $($tail)*)
    };
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
fn main() {
    define! {
        n: usize
        m: usize
    }
    let position = read_values::<i64>();
    let restaurants: Vec<Vec<i64>> = read_lines(n, |str| str.split(' ').map(|x| x.parse::<i64>().unwrap()).collect::<Vec<_>>());
    let mut memo: Vec<Vec<i64>> = vec![vec![0i64; n + 1]; n + 1];
    for t in 0 .. m {
        let mut stack = Vec::<usize>::new();
        for (next, restaurant) in restaurants.iter().enumerate() {
            let value = restaurant[t];
            while let Some(&mid) = stack.last() {
                if restaurants[mid][t] <= value {
                    stack.pop();
                    if let Some(&prev) = stack.last() {
                        memo[prev + 1][mid] += restaurants[mid][t];
                        memo[mid + 1][next] += restaurants[mid][t]; 
                        memo[mid + 1][mid] -= restaurants[mid][t];
                        memo[prev + 1][next] -= restaurants[mid][t];
                    }else {
                        memo[0][mid] += restaurants[mid][t];
                        memo[mid + 1][next] += restaurants[mid][t];
                        memo[mid + 1][mid] -= restaurants[mid][t];
                        memo[0][next] -= restaurants[mid][t];
                    }
                }else {
                    break;
                }
            }
            stack.push(next);
        }
        while let Some(mid) = stack.pop() {
            if let Some(&prev) = stack.last() {
                memo[prev + 1][mid] += restaurants[mid][t];
                memo[mid + 1][n] += restaurants[mid][t];
                memo[mid + 1][mid] -= restaurants[mid][t];
                memo[prev + 1][n] -= restaurants[mid][t];
            }else {
                memo[0][mid] += restaurants[mid][t];
                memo[mid + 1][n] += restaurants[mid][t];
                memo[mid + 1][mid] -= restaurants[mid][t];
                memo[0][n] -= restaurants[mid][t];
            }
        }
    }
    for i in 1 ..= n {
        for j in 0 ..= n {
            memo[i][j] += memo[i - 1][j];
        }
    }
    for i in 0 ..= n {
        for j in 1 ..= n {
            memo[i][j] += memo[i][j - 1];
        }
    }
    let mut diff = vec![0i64];
    for pos in position {
        diff.push(diff.last().unwrap() + pos);
    }
    freeze!(diff);
    let mut result = 0i64;
    for i in 0 .. n {
        for j in i .. n {
            result = max(result, diff[i] - diff[j] + memo[i][j]);
        }
    }
    println!("{}", result);
}


Measured memory_bytes: 207916