File size: 3,127 Bytes
14c9c2b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <functional>
#include <tuple>

using namespace std;

long long n;
long long k;

map<pair<int, int>, long long> memo;

long long do_query(int r, int c) {
    if (memo.count({r, c})) {
        return memo[{r, c}];
    }
    cout << "QUERY " << r << " " << c << endl;
    long long v;
    cin >> v;
    return memo[{r, c}] = v;
}

void done(long long ans) {
    cout << "DONE " << ans << endl;
}

void solve_dijkstra_min() {
    priority_queue<tuple<long long, int, int>, vector<tuple<long long, int, int>>, greater<tuple<long long, int, int>>> pq;
    vector<vector<bool>> visited(n + 1, vector<bool>(n + 1, false));

    long long val = do_query(1, 1);
    pq.emplace(val, 1, 1);
    visited[1][1] = true;

    long long result = -1;
    for (long long i = 0; i < k; ++i) {
        auto [v, r, c] = pq.top();
        pq.pop();
        result = v;

        if (r + 1 <= n && !visited[r + 1][c]) {
            long long next_val = do_query(r + 1, c);
            pq.emplace(next_val, r + 1, c);
            visited[r + 1][c] = true;
        }
        if (c + 1 <= n && !visited[r][c + 1]) {
            long long next_val = do_query(r, c + 1);
            pq.emplace(next_val, r, c + 1);
            visited[r][c + 1] = true;
        }
    }
    done(result);
}

void solve_dijkstra_max() {
    long long k_rev = n * n - k + 1;
    priority_queue<tuple<long long, int, int>> pq;
    vector<vector<bool>> visited(n + 1, vector<bool>(n + 1, false));

    long long val = do_query(n, n);
    pq.emplace(val, n, n);
    visited[n][n] = true;

    long long result = -1;
    for (long long i = 0; i < k_rev; ++i) {
        auto [v, r, c] = pq.top();
        pq.pop();
        result = v;

        if (r - 1 >= 1 && !visited[r - 1][c]) {
            long long next_val = do_query(r - 1, c);
            pq.emplace(next_val, r - 1, c);
            visited[r - 1][c] = true;
        }
        if (c - 1 >= 1 && !visited[r][c - 1]) {
            long long next_val = do_query(r, c - 1);
            pq.emplace(next_val, r, c - 1);
            visited[r][c - 1] = true;
        }
    }
    done(result);
}

long long count_le(long long val) {
    long long count = 0;
    int c = n;
    for (int r = 1; r <= n; ++r) {
        while (c >= 1 && do_query(r, c) > val) {
            c--;
        }
        count += c;
    }
    return count;
}

void solve_binary_search() {
    long long low = do_query(1, 1);
    long long high = do_query(n, n);
    long long ans = high;

    while (low <= high) {
        long long mid = low + (high - low) / 2;
        if (count_le(mid) >= k) {
            ans = mid;
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }
    done(ans);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> k;

    long long dijkstra_k_threshold = 24500;
    if (k <= dijkstra_k_threshold) {
        solve_dijkstra_min();
    } else if (n * n - k + 1 <= dijkstra_k_threshold) {
        solve_dijkstra_max();
    } else {
        solve_binary_search();
    }

    return 0;
}