#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>
#include <algorithm>
using namespace std;
int main() {
ifstream fin("plantatie.in");
ofstream fout("plantatie.out");
int N, M;
fin >> N >> M;
vector<vector<int>> productivitate(N, vector<int>(N));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
fin >> productivitate[i][j];
}
}
vector<tuple<int, int, int>> interogari(M);
for (int i = 0; i < M; ++i) {
int x, y, k;
fin >> x >> y >> k;
interogari[i] = make_tuple(x - 1, y - 1, k);
}
int logN = log2(N) + 1;
vector<vector<vector<vector<int>>>> sparse(logN, vector<vector<vector<int>>>(logN, vector<vector<int>>(N, vector<int>(N))));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
sparse[0][0][i][j] = productivitate[i][j];
}
}
for (int a = 0; a < logN; ++a) {
for (int b = 0; b < logN; ++b) {
if (a == 0 && b == 0) continue;
for (int i = 0; i + (1 << a) <= N; ++i) {
for (int j = 0; j + (1 << b) <= N; ++j) {
if (a == 0) {
sparse[a][b][i][j] = max(sparse[a][b - 1][i][j], sparse[a][b - 1][i][j + (1 << (b - 1))]);
} else if (b == 0) {
sparse[a][b][i][j] = max(sparse[a - 1][b][i][j], sparse[a - 1][b][i + (1 << (a - 1))][j]);
} else {
int max1 = max(sparse[a - 1][b - 1][i][j], sparse[a - 1][b - 1][i][j + (1 << (b - 1))]);
int max2 = max(sparse[a - 1][b - 1][i + (1 << (a - 1))][j], sparse[a - 1][b - 1][i + (1 << (a - 1))][j + (1 << (b - 1))]);
sparse[a][b][i][j] = max(max1, max2);
}
}
}
}
}
vector<int> rezultate(M);
for (int idx = 0; idx < M; ++idx) {
int x = get<0>(interogari[idx]);
int y = get<1>(interogari[idx]);
int k = get<2>(interogari[idx]);
int a = log2(k);
int b = log2(k);
int max1 = max(sparse[a][b][x][y], sparse[a][b][x + k - (1 << a)][y]);
int max2 = max(sparse[a][b][x][y + k - (1 << b)], sparse[a][b][x + k - (1 << a)][y + k - (1 << b)]);
rezultate[idx] = max(max1, max2);
}
for (const int& rezultat : rezultate) {
fout << rezultat << '\n';
}
fin.close();
fout.close();
return 0;
}