#include <bits/stdc++.h>
using namespace std;

// Provided by the judge
long long value(int r, int c);

namespace {
    const long long INF = (long long)4e18;

    int N_global, M_global;
    map<pair<int,int>, long long> memo;

    long long getVal(int r, int c) {
        if (r < 1 || r > N_global || c < 1 || c > M_global) return INF;

        pair<int,int> p = {r, c};
        auto it = memo.find(p);
        if (it != memo.end()) return it->second;

        long long v = value(r, c);
        memo[p] = v;
        return v;
    }

    bool isLocalMin(int r, int c) {
        long long v = getVal(r, c);
        return v < getVal(r - 1, c) &&
               v < getVal(r + 1, c) &&
               v < getVal(r, c - 1) &&
               v < getVal(r, c + 1);
    }

    pair<int,int> solveRow(int row, int left, int right) {
        while (left <= right) {
            int mid = (left + right) / 2;

            long long cur = getVal(row, mid);
            long long lv = getVal(row, mid - 1);
            long long rv = getVal(row, mid + 1);

            if (cur < lv && cur < rv) {
                return {row, mid};
            }
            if (lv < cur) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }

        return {row, left};
    }

    pair<int,int> solveCol(int col, int top, int bottom) {
        while (top <= bottom) {
            int mid = (top + bottom) / 2;

            long long cur = getVal(mid, col);
            long long uv = getVal(mid - 1, col);
            long long dv = getVal(mid + 1, col);

            if (cur < uv && cur < dv) {
                return {mid, col};
            }
            if (uv < cur) {
                bottom = mid - 1;
            } else {
                top = mid + 1;
            }
        }

        return {top, col};
    }

    pair<int,int> solve(int top, int bottom, int left, int right) {
        if (top == bottom) {
            return solveRow(top, left, right);
        }

        if (left == right) {
            return solveCol(left, top, bottom);
        }

        int midRow = (top + bottom) / 2;
        int midCol = (left + right) / 2;

        pair<int,int> best = {midRow, left};

        for (int c = left; c <= right; c++) {
            if (getVal(midRow, c) < getVal(best.first, best.second)) {
                best = {midRow, c};
            }
        }

        for (int r = top; r <= bottom; r++) {
            if (getVal(r, midCol) < getVal(best.first, best.second)) {
                best = {r, midCol};
            }
        }

        int r = best.first;
        int c = best.second;

        if (isLocalMin(r, c)) return best;

        pair<int,int> nxt = best;
        long long bestNeighborVal = getVal(r, c);

        const int dr[4] = {-1, 1, 0, 0};
        const int dc[4] = {0, 0, -1, 1};

        for (int k = 0; k < 4; k++) {
            int nr = r + dr[k];
            int nc = c + dc[k];
            if (nr < top || nr > bottom || nc < left || nc > right) continue;

            long long v = getVal(nr, nc);
            if (v < bestNeighborVal) {
                bestNeighborVal = v;
                nxt = {nr, nc};
            }
        }

        int nr = nxt.first;
        int nc = nxt.second;

        if (nr < midRow && nc < midCol) {
            return solve(top, midRow - 1, left, midCol - 1);
        } else if (nr < midRow && nc > midCol) {
            return solve(top, midRow - 1, midCol + 1, right);
        } else if (nr > midRow && nc < midCol) {
            return solve(midRow + 1, bottom, left, midCol - 1);
        } else if (nr > midRow && nc > midCol) {
            return solve(midRow + 1, bottom, midCol + 1, right);
        } else if (nr == midRow) {
            if (nc < midCol) return solve(top, bottom, left, midCol - 1);
            else             return solve(top, bottom, midCol + 1, right);
        } else {
            if (nr < midRow) return solve(top, midRow - 1, left, right);
            else             return solve(midRow + 1, bottom, left, right);
        }
    }
}

pair<int, int> find_locmin_point(int N, int M) {
    N_global = N;
    M_global = M;
    memo.clear();
    return solve(1, N, 1, M);
}