#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define rep(x, to) for (int x = 0; x < (to); x++) #define REP(x, a, to) for (int x = (a); x < (to); x++) #define foreach(itr, x) for (typeof((x).begin()) itr = (x).begin(); itr != (x).end(); itr++) #define EPS (1e-14) using namespace std; typedef long long ll; typedef pair PII; typedef pair PLL; typedef complex Complex; typedef vector< vector > Mat; int N, M; int E[10][805]; int ans_mx, ans_id; bool is_kadomatsu(int a, int b, int c) { if (a < b && b > c) return true; if (a > b && b < c) return true; else return false; } struct SegmentTreeMin { int n; int dat[100005]; void init(int m) { n = 1; while (n < m) { n *= 2; } for (int i = 0; i < 2 * n - 1; i++) { dat[i] = (int)(1e+9 + 7); } } void update(int i, int value) { i += n - 1; dat[i] = value; while (i > 0) { i = (i - 1) / 2; int chl = 2 * i + 1; int chr = 2 * i + 2; dat[i] = min(dat[chl], dat[chr]); } } //[a, b) node-k [l, r) int query(int a, int b, int k, int l, int r) { if (a <= l && r <= b) return dat[k]; if (b <= l || r <= a) return (int)(1e+9 + 7); int chl = 2 * k + 1; int chr = 2 * k + 2; return min(query(a, b, chl, l, (l + r)/2), query(a, b, chr, (l + r)/2, r)); } }; struct SegmentTreeMax { int n; int dat[100005]; string type; void init(int m) { n = 1; while (n < m) { n *= 2; } for (int i = 0; i < 2 * n - 1; i++) { dat[i] = 0; } } void update(int i, int value) { i += n - 1; dat[i] = value; while (i > 0) { i = (i - 1) / 2; int chl = 2 * i + 1; int chr = 2 * i + 2; dat[i] = max(dat[chl], dat[chr]); } } //[a, b) node-k [l, r) int query(int a, int b, int k, int l, int r) { if (a <= l && r <= b) return dat[k]; if (b <= l || r <= a) return 0; int chl = 2 * k + 1; int chr = 2 * k + 2; return max(query(a, b, chl, l, (l + r)/2), query(a, b, chr, (l + r)/2, r)); } }; SegmentTreeMin seg_min; SegmentTreeMax seg_max; ll calc(int p) { int res = 0; seg_min.init(N); seg_max.init(N); for (int i = 0; i < N; i++) { seg_min.update(i, E[p][i]); seg_max.update(i, E[p][i]); } #if 0 for (int i = 0; i < N; i++) { for (int j = i + 1; j < N; j++) { printf("[%d,%d) min %d\n", i, j+1, seg_min.query(i, j+1, 0, 0, seg_min.n)); printf("[%d,%d) max %d\n", i, j+1, seg_max.query(i, j+1, 0, 0, seg_max.n)); } } #endif for (int i = 0; i < N; i++) { for (int j = i + 1; j < N; j++) { int mx = 0; int x = 0; //[i, j) x = seg_min.query(i, j, 0, 0, seg_min.n); if (is_kadomatsu(E[p][i], x, E[p][j])) { mx = max(mx, max(x, max(E[p][i], E[p][j]))); } x = seg_max.query(i, j, 0, 0, seg_max.n); if (is_kadomatsu(E[p][i], x, E[p][j])) { mx = max(mx, max(x, max(E[p][i], E[p][j]))); } if (E[p][i] < E[p][j]) { //[0, i) x = seg_max.query(0, i, 0, 0, seg_max.n); if (is_kadomatsu(x, E[p][i], E[p][j])) { mx = max(mx, max(x, E[p][j])); } //[j, N) x = seg_min.query(j, N, 0, 0, seg_min.n); if (is_kadomatsu(E[p][i], E[p][j], x)) { mx = max(mx, E[p][j]); } } else { // E[p][i] > E[p][j] // [0, i) x = seg_min.query(0, i, 0, 0, seg_min.n); if (is_kadomatsu(x, E[p][i], E[p][j])) { mx = max(mx, E[p][i]); } // [j, N) x = seg_max.query(j, N, 0, 0, seg_max.n); if (is_kadomatsu(E[p][i], E[p][j], x)) { mx = max(mx, max(E[p][i], x)); } } #if 0 printf("%d,%d => %d\n", i, j, mx); #endif res += mx; } } return res; } void solve() { for (int i = 0; i < M; i++) { int mx = calc(i); if (ans_mx < mx) { ans_mx = mx; ans_id = i; } } cout<< ans_id << endl; } int main() { cin >> N >> M; rep(i, M) rep(j, N) { cin >> E[i][j]; } solve(); return 0; }