#include template using vc = std::vector; template using vvc = std::vector>; struct CustomHash { static constexpr uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } static constexpr size_t append(size_t x, size_t y) { return x ^ (y >> 1) ^ ((y & 1) << (sizeof(size_t) * 8 - 1)); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } template size_t operator()(std::pair const &p) const { return append((*this)(p.first), (*this)(p.second)); } template size_t operator()(std::tuple const &tp) const { size_t ret = 0; std::apply( [&](Ts const &...targs) { ((ret = append(ret, (*this)(targs))), ...); }, tp); return ret; } template < class Tp, std::enable_if_t().begin()), typename Tp::iterator>::value && std::is_same().end()), typename Tp::iterator>::value> * = nullptr> size_t operator()(Tp const &tp) const { size_t ret = 0; for (auto &&i : tp) ret = append(ret, (*this)(i)); return ret; } }; using u32 = uint32_t; template constexpr auto chkmin(Tp &a, Tp b) -> bool { return b < a ? a = b, true : false; } template constexpr auto chkmax(Tp &a, Tp b) -> bool { return a < b ? a = b, true : false; } template constexpr auto ispow2(Tp i) -> bool { return i && (i & -i) == i; } #define TPL_SIZE_(Tuple) std::tuple_size_v> namespace tuple_detail_ { template constexpr auto subtuple_impl_(Tuple &&t, std::index_sequence) { return std::make_tuple(std::get(t)...); } template constexpr auto apply2_impl_(BinOp &&f, Tuple &&lhs, Tuple &&rhs, std::index_sequence) { return std::make_tuple( std::forward(f)(std::get(lhs), std::get(rhs))...); } } // namespace tuple_detail_ template constexpr auto subtuple(Tuple &&t) { static_assert(Begin <= TPL_SIZE_(Tuple) && Len <= TPL_SIZE_(Tuple) && Begin + Len <= TPL_SIZE_(Tuple), "Out of range"); return tuple_detail_::subtuple_impl_(t, std::make_index_sequence()); } template constexpr auto tuple_push(Tp &&v, Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), std::make_tuple(v), subtuple(t)); } template constexpr auto tuple_push_front(Tp &&v, Tuple &&t) { return tuple_push<0>(v, t); } template constexpr auto tuple_push_back(Tp &&v, Tuple &&t) { return tuple_push(v, t); } template constexpr auto tuple_pop(Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), subtuple(t)); } template constexpr auto tuple_pop_front(Tuple &&t) { return tuple_pop<0>(t); } template constexpr auto tuple_pop_back(Tuple &&t) { return tuple_pop(t); } template constexpr auto apply2(BinOp &&f, Tuple &&lhs, Tuple &&rhs) { return tuple_detail_::apply2_impl_( f, lhs, rhs, std::make_index_sequence()); } #define OO_PTEQ_(op) \ template \ constexpr auto operator op(std::pair lhs, \ const std::pair &rhs) { \ return std::pair{lhs.first op rhs.first, \ lhs.second op rhs.second}; \ } \ template \ constexpr auto operator op(std::tuple const &lhs, \ std::tuple const &rhs) { \ return apply2([](auto &&l, auto &&r) { return l op r; }, lhs, rhs); \ } \ template \ constexpr std::pair &operator op##=(std::pair &lhs, \ const std::pair &rhs) { \ lhs.first op## = rhs.first; \ lhs.second op## = rhs.second; \ return lhs; \ } \ template \ constexpr auto operator op##=(std::tuple &lhs, \ const std::tuple &rhs) { \ return lhs = lhs op rhs; \ } OO_PTEQ_(+) OO_PTEQ_(-) OO_PTEQ_(*) OO_PTEQ_(/) OO_PTEQ_(%) OO_PTEQ_(&) OO_PTEQ_(|) OO_PTEQ_(^) OO_PTEQ_(<<) OO_PTEQ_(>>) #undef OO_PTEQ_ #undef TPL_SIZE_ template std::istream &operator>>(std::istream &is, std::pair &p) { return is >> p.first >> p.second; } template std::ostream &operator<<(std::ostream &os, const std::pair &p) { return os << p.first << ' ' << p.second; } template std::istream &operator>>(std::istream &is, std::tuple &p) { std::apply([&](Ts &...targs) { ((is >> targs), ...); }, p); return is; } template std::ostream &operator<<(std::ostream &os, const std::tuple &p) { std::apply( [&](Ts const &...targs) { std::size_t n{0}; ((os << targs << (++n != sizeof...(Ts) ? " " : "")), ...); }, p); return os; } template < class Ch, class Tr, class Ct, std::enable_if_t().begin()), typename Ct::iterator>::value && std::is_same().end()), typename Ct::iterator>::value> * = nullptr> std::basic_ostream &operator<<(std::basic_ostream &os, const Ct &x) { if (x.begin() == x.end()) return os; for (auto it = x.begin(); it != x.end() - 1; ++it) os << *it << ' '; os << x.back(); return os; } const u32 K = 21; using namespace std; template > class RMQ_ST_2D { protected: query_func qfunc; std::vector>> f; public: RMQ_ST_2D() = delete; RMQ_ST_2D(query_func qfunc): qfunc(qfunc), f() {} template > void init(size_t n, size_t m, init_func ifunc) { const size_t K = (size_t)std::log2(std::max(n, m)) + 1; f.resize(K); for (auto &i : f) { i.resize(n); for (auto &j : i) j.resize(m); } for (size_t i = 0; i < n; ++i) for (size_t j = 0; j < m; ++j) f[0][i][j] = ifunc(i, j); for (size_t k = 1, p = 1, q = 2; k < K; ++k, p = q, q *= 2) for (int i = 0; i + q - 1 < n; ++i) for (int j = 0; j + q - 1 < m; ++j) f[k][i][j] = qfunc(qfunc(f[k - 1][i][j], f[k - 1][i + p][j]), qfunc(f[k - 1][i][j + p], f[k - 1][i + p][j + p])); } data_t query(size_t x, size_t y, size_t l) const { size_t _ = (size_t)std::log2(l); return qfunc(qfunc(f[_][x][y], f[_][x + l - (1 << _)][y]), qfunc(f[_][x][y + l - (1 << _)], f[_][x + l - (1 << _)][y + l - (1 << _)])); } }; auto solve([[maybe_unused]] int t_ = 0) -> void { int n, m; cin >> n >> m; vvc a(n, vc(m)); for (auto &i : a) for (auto &j : i) cin >> j; RMQ_ST_2D st([](int x, int y) { return min(x, y); }); st.init(n, m, [&](size_t x, size_t y) { return a[x][y]; }); auto check = [&](int g) { int mx = 0; for (int i = 0; i <= n - g; ++i) for (int j = 0; j <= m - g; ++j) mx = max(mx, st.query(i, j, g)); return mx >= g; }; int l = 1, r = min(n, m), ans = l; while (l <= r) { auto m = r - (r - l) / 2; if (check(m)) l = (ans = m) + 1; else r = m - 1; } cout << ans << '\n'; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int i_ = 0; int t_ = 0; std::cin >> t_; for (i_ = 0; i_ < t_; ++i_) solve(i_); return 0; }