| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <random> |
|
|
| using namespace std; |
|
|
| |
| int n; |
| long long k; |
| long long memo[2005][2005]; |
| bool visited[2005][2005]; |
|
|
| |
| |
| long long query(int r, int c) { |
| if (visited[r][c]) return memo[r][c]; |
| cout << "QUERY " << r << " " << c << endl; |
| long long val; |
| cin >> val; |
| visited[r][c] = true; |
| memo[r][c] = val; |
| return val; |
| } |
|
|
| |
| void done(long long ans) { |
| cout << "DONE " << ans << endl; |
| exit(0); |
| } |
|
|
| |
| |
| |
| int L[2005]; |
| int R[2005]; |
|
|
| int main() { |
| |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
|
|
| if (!(cin >> n >> k)) return 0; |
|
|
| |
| for (int i = 1; i <= n; ++i) { |
| L[i] = 0; |
| R[i] = n + 1; |
| } |
|
|
| long long count_L = 0; |
| mt19937 rng(1337); |
| int stuck_cnt = 0; |
|
|
| while (true) { |
| long long S = 0; |
| vector<int> active_rows; |
| for (int i = 1; i <= n; ++i) { |
| if (L[i] < R[i] - 1) { |
| S += (R[i] - 1 - L[i]); |
| active_rows.push_back(i); |
| } |
| } |
|
|
| |
| if (S <= 850) { |
| vector<long long> vals; |
| for (int r : active_rows) { |
| for (int c = L[r] + 1; c < R[r]; ++c) { |
| vals.push_back(query(r, c)); |
| } |
| } |
| sort(vals.begin(), vals.end()); |
| |
| long long idx = k - count_L - 1; |
| if (idx >= 0 && idx < vals.size()) { |
| done(vals[idx]); |
| } else { |
| |
| if (!vals.empty()) done(vals.back()); |
| else break; |
| } |
| } |
|
|
| |
| long long rand_idx = uniform_int_distribution<long long>(0, S - 1)(rng); |
| int r_pivot = -1, c_pivot = -1; |
| long long current_s = 0; |
| for (int r : active_rows) { |
| long long width = R[r] - 1 - L[r]; |
| if (current_s + width > rand_idx) { |
| r_pivot = r; |
| c_pivot = L[r] + 1 + (rand_idx - current_s); |
| break; |
| } |
| current_s += width; |
| } |
|
|
| long long pivot = query(r_pivot, c_pivot); |
| |
| |
| |
| vector<int> path_c(n + 1); |
| long long cnt_le = 0; |
| int c = 0; |
| for (int i = n; i >= 1; --i) { |
| |
| int curr = max(c, L[i] + 1); |
| while (curr < R[i]) { |
| long long val = query(i, curr); |
| if (val > pivot) break; |
| curr++; |
| } |
| path_c[i] = curr - 1; |
| c = path_c[i]; |
| cnt_le += path_c[i]; |
| } |
|
|
| bool changed = false; |
| |
| if (cnt_le < k) { |
| |
| |
| for(int i = 1; i <= n; ++i) { |
| if (L[i] != path_c[i]) changed = true; |
| L[i] = path_c[i]; |
| } |
| count_L = cnt_le; |
| stuck_cnt = 0; |
| } else { |
| |
| |
| for(int i = 1; i <= n; ++i) { |
| if (R[i] != path_c[i] + 1) changed = true; |
| R[i] = path_c[i] + 1; |
| } |
| |
| if (!changed) { |
| |
| |
| stuck_cnt++; |
| if (stuck_cnt > 10) done(pivot); |
| } else { |
| stuck_cnt = 0; |
| } |
| } |
| } |
| return 0; |
| } |