| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <random> |
|
|
| using namespace std; |
|
|
| |
| |
| vector<long long> memo; |
| int n; |
| long long k; |
|
|
| |
| |
| long long query(int r, int c) { |
| if (r < 0 || r >= n || c < 0 || c >= n) return -2; |
| if (memo[r * n + c] != -1) { |
| return memo[r * n + c]; |
| } |
| cout << "QUERY " << r + 1 << " " << c + 1 << endl; |
| long long val; |
| cin >> val; |
| memo[r * n + c] = val; |
| return val; |
| } |
|
|
| int main() { |
| |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
|
|
| if (!(cin >> n >> k)) return 0; |
|
|
| |
| memo.assign(n * n, -1); |
|
|
| |
| |
| |
| vector<int> L(n, 0); |
| vector<int> R(n, n); |
|
|
| |
| mt19937_64 rng(1337); |
|
|
| while (true) { |
| |
| long long total_candidates = 0; |
| for (int i = 0; i < n; ++i) { |
| if (L[i] < R[i]) { |
| total_candidates += (R[i] - L[i]); |
| } |
| } |
|
|
| if (total_candidates == 0) break; |
|
|
| |
| long long pick = std::uniform_int_distribution<long long>(0, total_candidates - 1)(rng); |
| |
| int pivot_r = -1, pivot_c = -1; |
| long long current_idx = 0; |
| |
| |
| for (int i = 0; i < n; ++i) { |
| long long width = R[i] - L[i]; |
| if (width > 0) { |
| if (current_idx + width > pick) { |
| pivot_r = i; |
| pivot_c = L[i] + (int)(pick - current_idx); |
| break; |
| } |
| current_idx += width; |
| } |
| } |
| |
| long long pivot_val = query(pivot_r, pivot_c); |
|
|
| |
| long long count_le = 0; |
| vector<int> boundary(n); |
| |
| |
| |
| int curr_c = n - 1; |
| |
| for (int i = 0; i < n; ++i) { |
| |
| if (i > 0) curr_c = min(curr_c, boundary[i-1]); |
| curr_c = min(curr_c, R[i] - 1); |
| |
| |
| while (curr_c >= L[i]) { |
| long long val = query(i, curr_c); |
| if (val <= pivot_val) break; |
| curr_c--; |
| } |
| |
| boundary[i] = curr_c; |
| count_le += (curr_c + 1); |
| } |
| |
| if (count_le >= k) { |
| |
| |
| |
| |
| |
| bool changed = false; |
| for (int i = 0; i < n; ++i) { |
| if (R[i] > boundary[i] + 1) { |
| R[i] = boundary[i] + 1; |
| changed = true; |
| } |
| } |
| |
| |
| |
| if (!changed) { |
| cout << "DONE " << pivot_val << endl; |
| return 0; |
| } |
| } else { |
| |
| |
| |
| |
| |
| bool changed = false; |
| for (int i = 0; i < n; ++i) { |
| if (L[i] <= boundary[i]) { |
| L[i] = boundary[i] + 1; |
| changed = true; |
| } |
| } |
| } |
| } |
|
|
| return 0; |
| } |