#include #include #include #include #include // Using a map for memoization for queried cell values. std::map, long long> memo; long long n_val; // Function to perform a query and cache the result. long long do_query(int r, int c) { if (memo.count({r, c})) { return memo[{r, c}]; } std::cout << "QUERY " << r << " " << c << std::endl; long long v; std::cin >> v; if (std::cin.fail()) { // In case of an error from the judge or unexpected termination. exit(0); } return memo[{r, c}] = v; } // Counts the number of elements in the matrix less than or equal to `val`. // This uses a "staircase" search pattern, making at most 2n new queries. long long count_le(long long val) { long long count = 0; int c = n_val; for (int r = 1; r <= n_val; ++r) { while (c > 0 && do_query(r, c) > val) { c--; } count += c; } return count; } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); long long k_val; std::cin >> n_val >> k_val; long long lo, hi; if (n_val > 0) { // Initialize search range with min and max possible values. lo = do_query(1, 1); hi = do_query(n_val, n_val); } else { // Edge case for n=0, though constraints likely prevent this. std::cout << "DONE " << 0 << std::endl; return 0; } long long ans = hi; // Binary search for the k-th smallest value. while (lo <= hi) { long long mid = lo + (hi - lo) / 2; if (count_le(mid) >= k_val) { ans = mid; hi = mid - 1; } else { lo = mid + 1; } } std::cout << "DONE " << ans << std::endl; return 0; }