Problem: cf1498_e
Difficulty: easy
Categories: graph, greedy, data structures
Time limit: 3500 ms, memory limit: 256 MB

This is an interactive problem. Remember to flush your output while communicating with the testing program. You may use fflush(stdout) in C++, system.out.flush() in Java, stdout.flush() in Python or flush(output) in Pascal to flush the output. If you use some other programming language, consult its documentation. You may also refer to the guide on interactive problems: [link omitted].

There is a city in which Dixit lives. In the city, there are $n$ houses. There is  exactly one directed road between every pair of houses. For example, consider two houses A and B, then there is a directed road either from A to B or from B to A but not both. The number of roads leading to the $i$-th house is $k_i$.

Two houses A and B are bi-reachable if A is reachable from B and B is reachable from A. We say that house B is reachable from house A when there is a path from house A to house B.

Dixit wants to buy two houses in the city, that is, one for living and one for studying. Of course, he would like to travel from one house to another. So, he wants to find a pair of bi-reachable houses A and B. Among all such pairs, he wants to choose one with the maximum value of $|k_A - k_B|$, where $k_i$ is the number of roads leading to the house $i$. If more than one optimal pair exists, any of them is suitable.

Since Dixit is busy preparing CodeCraft, can you help him find the desired pair of houses, or tell him that no such houses exist?

In the problem input, you are not given the direction of each road. You are given — for each house — only the number of incoming roads to that house ($k_i$).

You are allowed to ask only one type of query from the judge: give two houses A and B, and the judge answers whether B is reachable from A. There is no upper limit on the number of queries. But, you cannot ask more queries after the judge answers "Yes" to any of your queries. Also, you cannot ask the same query twice.

Once you have exhausted all your queries (or the judge responds "Yes" to any of your queries), your program must output its guess for the two houses and quit.

See the Interaction section below for more details.

Input

The first line contains a single integer $n$ ($3 \le n \le 500$) denoting the number of houses in the city. The next line contains $n$ space-separated integers $k_1, k_2, \dots, k_n$ ($0 \le k_i \le n - 1$), the $i$-th of them represents the number of incoming roads to the $i$-th house.

Interaction

To ask a query, print "? A B" $(1 \leq A,B \leq N, A\neq B)$. The judge will respond "Yes" if house B is reachable from house A, or "No" otherwise.

To output the final answer, print "! A B", where A and B are bi-reachable with the maximum possible value of $|k_A - k_B|$. If there does not exist such pair of houses A and B, output "! 0 0".

After outputting the final answer, your program must terminate immediately, otherwise you will receive Wrong Answer verdict.

You cannot ask the same query twice. There is no upper limit to the number of queries you ask, but, you cannot ask more queries after the judge answers "Yes" to any of your queries. Your program must now output the final answer ("! A B" or "! 0 0") and terminate.

If you ask a query in incorrect format or repeat a previous query, you will get Wrong Answer verdict.

After printing a query do not forget to output the end of the line and flush the output. Otherwise, you will get the Idleness limit exceeded error. To do this, use:

* fflush(stdout) or cout.flush() in C++;
* System.out.flush() in Java;
* flush(output) in Pascal;
* stdout.flush() in Python;
* see documentation for other languages.

Examples

Input

```
3
1 1 1
Yes
```

Output

```? 1 2! 1 2
```

Input

```
4
1 2 0 3
No
No
No
No
No
No
```

Output

```? 2 1? 1 3? 4 1? 2 3? 4 2? 4 3! 0 0
```

Note

In the first sample input, we are given a city of three houses with one incoming road each. The user program asks one query: "? 1 2": asking whether we can reach from house $1$ to house $2$. The judge responds with "Yes". The user program now concludes that this is sufficient information to determine the correct answer. So, it outputs "! 1 2" and quits.

In the second sample input, the user program queries for six different pairs of houses, and finally answers "! 0 0" as it is convinced that no two houses as desired in the question exist in this city.

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
#include <csignal>

using namespace std;


















long long queries = 0;


long long query_limit = 250000; 


int n;
vector<int> degrees;
vector<bitset<500>> reach; 
int max_diff = -1; 
bool yes_answered = false;
set<pair<int,int>> history;


void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {}
}


void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

int main(int argc, char** argv) {
    
    signal(SIGPIPE, SIG_IGN);

    registerInteraction(argc, argv);
    atexit(log_metrics);

    
    
    n = inf.readInt();
    degrees.resize(n);
    for(int i = 0; i < n; ++i) {
        degrees[i] = inf.readInt();
    }

    
    reach.resize(n);
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < n; ++j) {
            int edge = inf.readInt(); 
            if(edge) {
                reach[i][j] = 1;
            }
        }
        reach[i][i] = 1; 
    }

    
    
    for(int k = 0; k < n; ++k) {
        for(int i = 0; i < n; ++i) {
            if(reach[i][k]) {
                reach[i] |= reach[k];
            }
        }
    }

    
    
    for(int i = 0; i < n; ++i) {
        for(int j = i + 1; j < n; ++j) {
            
            if(reach[i][j] && reach[j][i]) {
                int diff = abs(degrees[i] - degrees[j]);
                if(diff > max_diff) {
                    max_diff = diff;
                }
            }
        }
    }

    
    cout << n << endl;
    for(int i = 0; i < n; ++i) {
        cout << degrees[i] << (i == n - 1 ? "" : " ");
    }
    cout << endl; 

    
    while(true) {
        
        if(queries % 10 == 0) log_metrics();

        string token;
        if(!(cin >> token)) {
            finish(_pe, "Unexpected EOF (contestant exited without answer)");
        }

        if(token == "!") {
            int u, v;
            if(!(cin >> u >> v)) {
                finish(_pe, "Invalid answer format");
            }

            
            if(u == 0 && v == 0) {
                if(max_diff == -1) {
                    finish(_ok, "Correct (no solution)");
                } else {
                    finish(_wa, "Contestant found no solution, but one exists with diff " + to_string(max_diff));
                }
            } else {
                
                if(u < 1 || u > n || v < 1 || v > n || u == v) {
                    finish(_wa, "Invalid house indices in answer");
                }
                
                int u_idx = u - 1;
                int v_idx = v - 1;

                
                if(!reach[u_idx][v_idx] || !reach[v_idx][u_idx]) {
                    finish(_wa, "Houses are not bi-reachable");
                }

                
                int diff = abs(degrees[u_idx] - degrees[v_idx]);
                if(diff < max_diff) {
                    finish(_wa, "Found valid pair but difference (" + to_string(diff) + 
                                ") is not maximum (max=" + to_string(max_diff) + ")");
                }

                finish(_ok, "Correct");
            }
        } else {
            
            int u, v;
            if(token == "?") {
                if(!(cin >> u >> v)) finish(_pe, "Invalid query format");
            } else {
                
                try {
                    u = stoi(token);
                } catch(...) {
                    finish(_pe, "Invalid token '" + token + "'");
                }
                if(!(cin >> v)) finish(_pe, "Invalid query format (missing second integer)");
            }

            
            if(yes_answered) {
                finish(_wa, "Protocol violation: query asked after receiving 'Yes'");
            }
            if(u < 1 || u > n || v < 1 || v > n || u == v) {
                finish(_wa, "Invalid query indices");
            }
            if(history.count({u, v})) {
                finish(_wa, "Repeated query");
            }
            history.insert({u, v});

            
            bool res = (reach[u-1][v-1] == 1);
            cout << (res ? "Yes" : "No") << endl;

            queries++;
            if(res) yes_answered = true;

            
            if(queries > 300000) {
                finish(_pe, "Hard query limit exceeded");
            }
        }
    }

    return 0;
}


Adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;


static long long queries = 0;
static long long query_limit = 0;


int n;
vector<int> k;          
vector<int> block;      
int global_max_diff = -1; 


static void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {}
}


static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}




void compute_blocks() {
    
    
    vector<pair<int, int>> sorted_k(n);
    for (int i = 1; i <= n; i++) {
        sorted_k[i - 1] = {k[i], i};
    }
    sort(sorted_k.begin(), sorted_k.end());

    block.assign(n + 1, 0);
    long long current_sum = 0;
    int current_block = 0;
    vector<int> current_indices;

    
    
    
    
    
    
    for (int j = 0; j < n; j++) {
        current_sum += sorted_k[j].first;
        current_indices.push_back(sorted_k[j].second);
        
        long long count = j + 1;
        
        if (current_sum == count * (count - 1) / 2) {
            
            for (int u : current_indices) {
                block[u] = current_block;
            }
            
            
            
            if (current_indices.size() >= 2) {
                for (size_t a = 0; a < current_indices.size(); a++) {
                    for (size_t b = a + 1; b < current_indices.size(); b++) {
                        int u = current_indices[a];
                        int v = current_indices[b];
                        int diff = abs(k[u] - k[v]);
                        if (diff > global_max_diff) {
                            global_max_diff = diff;
                        }
                    }
                }
            }
            
            current_block++;
            current_indices.clear();
        }
    }
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    
    n = inf.readInt();
    k.assign(n + 1, 0);
    for (int i = 1; i <= n; i++) {
        k[i] = inf.readInt();
    }
    
    
    
    query_limit = (long long)n * (n - 1) + 1000;

    
    cout << n << endl;
    for (int i = 1; i <= n; i++) {
        cout << k[i] << (i == n ? "" : " ");
    }
    cout << endl;
    
    
    log_metrics();

    
    compute_blocks();

    bool answered_yes = false;
    set<pair<int, int>> history;

    while (true) {
        string token;
        
        if (!(cin >> token)) {
            finish(_wa, "Unexpected EOF (did not receive final answer)");
        }

        if (token == "!") {
            int u, v;
            if (!(cin >> u >> v)) finish(_wa, "Invalid answer format");
            
            if (u == 0 && v == 0) {
                if (global_max_diff != -1) {
                    finish(_wa, "Contestant said no solution (! 0 0), but a pair exists");
                }
                finish(_ok, "Correct (no solution)");
            } else {
                if (u < 1 || u > n || v < 1 || v > n || u == v) {
                    finish(_wa, "Invalid indices in answer");
                }
                
                if (global_max_diff == -1) {
                    finish(_wa, "Contestant output a pair, but no valid pair exists");
                }
                
                
                if (block[u] != block[v]) {
                    finish(_wa, "Proposed pair is not bi-reachable");
                }
                
                int diff = abs(k[u] - k[v]);
                if (diff == global_max_diff) {
                    finish(_ok, "Correct");
                } else {
                    finish(_wa, "Not maximum difference");
                }
            }
        } 
        else if (token == "?") {
            if (answered_yes) {
                finish(_wa, "Queries not allowed after receiving 'Yes'");
            }
            
            int u, v;
            if (!(cin >> u >> v)) finish(_wa, "Invalid query format");
            
            if (u < 1 || u > n || v < 1 || v > n || u == v) {
                finish(_wa, "Invalid indices in query");
            }
            
            if (history.count({u, v})) {
                finish(_wa, "Repeated query");
            }
            history.insert({u, v});
            
            queries++;
            
            if (queries > 300000) {
                finish(_pe, "Query limit exceeded hard cap");
            }
            
            if (queries % 1000 == 0) log_metrics();
            
            
            
            
            
            
            bool result = (block[u] <= block[v]);
            
            cout << (result ? "Yes" : "No") << endl;
            
            if (result) answered_yes = true;
        } 
        else {
            finish(_wa, "Invalid token (expected ? or !)");
        }
    }
}


Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;






















vector<vector<int>> gen_random_tournament(int n) {
    vector<vector<int>> adj(n, vector<int>(n, 0));
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (rnd.next(2)) {
                adj[i][j] = 1;
                adj[j][i] = 0;
            } else {
                adj[i][j] = 0;
                adj[j][i] = 1;
            }
        }
    }
    return adj;
}






vector<vector<int>> gen_blocks(int n) {
    vector<int> parts;
    int type = rnd.next(3);
    
    
    if (n < 5) type = 0; 

    if (type == 0) { 
        
        int rem = n;
        while (rem > 0) {
            int s = rnd.next(1, min(rem, 5));
            parts.push_back(s);
            rem -= s;
        }
    } else if (type == 1) { 
        
        int k = rnd.next(2, max(2, min(n, 5)));
        parts = rnd.partition(k, n, 1);
    } else { 
        
        int k = rnd.next(1, n);
        parts = rnd.partition(k, n, 1);
    }

    vector<vector<int>> adj(n, vector<int>(n, 0));
    
    
    
    int current = 0;
    for (int s : parts) {
        
        for (int i = current; i < current + s; i++) {
            for (int j = i + 1; j < current + s; j++) {
                if (rnd.next(2)) {
                    adj[i][j] = 1; 
                } else {
                    adj[j][i] = 1; 
                }
            }
        }
        
        for (int i = current; i < current + s; i++) {
            for (int j = current + s; j < n; j++) {
                adj[i][j] = 1; 
            }
        }
        current += s;
    }

    
    vector<int> p(n);
    iota(p.begin(), p.end(), 0);
    shuffle(p.begin(), p.end());

    vector<vector<int>> final_adj(n, vector<int>(n));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            final_adj[p[i]][p[j]] = adj[i][j];
        }
    }
    return final_adj;
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);

    string mode = opt<string>("mode", "non");
    long long seed_val = atoll(argv[1]);
    
    int n;
    
    if (seed_val == 1) n = 3;
    else if (seed_val == 2) n = 4;
    else if (seed_val == 3) n = 500; 
    else {
        
        if (rnd.next(3) == 0) n = rnd.next(3, 20);
        else n = rnd.next(21, 500);
    }

    vector<vector<int>> adj;

    
    if (seed_val == 1) {
        
        adj = vector<vector<int>>(3, vector<int>(3, 0));
        
        adj[0][1] = 1; adj[1][2] = 1; adj[0][2] = 1;
        
        
        vector<int> p(3); iota(p.begin(), p.end(), 0);
        shuffle(p.begin(), p.end());
        vector<vector<int>> permed(3, vector<int>(3));
        for(int i=0; i<3; ++i) 
            for(int j=0; j<3; ++j) 
                permed[p[i]][p[j]] = adj[i][j];
        adj = permed;
    } 
    else if (seed_val == 2) {
        
        adj = gen_blocks(4);
    }
    else {
        
        
        
        if (rnd.next(100) < 30) {
            adj = gen_random_tournament(n);
        } else {
            adj = gen_blocks(n);
        }
    }

    
    vector<int> k(n, 0);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (adj[j][i] == 1) { 
                k[i]++;
            }
        }
    }

    
    cout << n << "\n";
    
    
    for (int i = 0; i < n; i++) {
        cout << k[i] << (i == n - 1 ? "" : " ");
    }
    cout << "\n";

    if (mode == "non") {
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cout << adj[i][j] << (j == n - 1 ? "" : " ");
            }
            cout << "\n";
        }
    } 
    
    
    
    return 0;
}