#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
//#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#pragma GCC optimize ("fast-math")
#define ezurect int T; cin >> T; while(T--){solve();}
const int N = 501, mod = 1e9 + 7, mod1 = 1e9 + 9;
int n, q;
int aint[N * 4][N * 4], matr[N][N];
void buildy(int vx, int tlx, int trx, int v, int tl, int tr){
if(tl == tr){
if(tlx == trx){
aint[vx][v] = matr[tlx][tl];
}else{
aint[vx][v] = max(aint[vx * 2][v], aint[vx * 2 + 1][v]);
}
return;
}
int tm = (tl + tr) / 2;
buildy(vx, tlx, trx, v * 2, tl, tm);
buildy(vx, tlx, trx, v * 2 + 1, tm + 1, tr);
aint[vx][v] = max(aint[vx][v * 2], aint[vx][v * 2 + 1]);
}
void build(int v, int tl, int tr){
if(tl != tr){
int tm = (tl + tr) / 2;
build(v * 2, tl, tm);
build(v * 2 + 1, tm + 1 ,tr);
}
buildy(v, tl, tr, 1, 1 ,n);
}
int queryy(int vx, int tlx, int trx, int v, int tl, int tr, int l, int r){
if(l <= tl && r >= tr){
return aint[vx][v];
}
if(tr < l || tl > r) return 0;
int tm = (tl + tr) / 2;
int m1 = queryy(vx, tlx, trx, v * 2, tl, tm, l, r);
int m2 = queryy(vx, tlx, trx, v * 2 + 1, tm + 1, tr, l, r);
return max(m1 , m2);
}
int query(int v, int tl, int tr, int a, int b, int c, int d){
if(a <= tl && b >= tr){
return queryy(v, tl, tr, 1, 1, n, c, d);
}
if(tr < a || tl > b) return 0;
int tm = (tl + tr) / 2;
int m1 = query(v * 2, tl, tm, a, b, c, d);
int m2 = query(v * 2 + 1, tm + 1, tr, a, b, c, d);
return max(m1, m2);
}
int main(){
ifstream fin("plantatie.in");
ofstream fout("plantatie.out");
fin.tie(0)->sync_with_stdio(0);
fin >> n >> q;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
fin >> matr[i][j];
}
}
build(1, 1, n);
while(q--){
int x, y, k;
fin >> x >> y >> k;
fout << query(1, 1, n, x, x + k - 1, y, y + k - 1) << '\n';
}
}