Problem: cf1764_g2
Difficulty: medium
Categories: search, math
Time limit: 1000 ms, memory limit: 256 MB

The only difference between this problem and the other two versions is the maximum number of queries. In this version, you are allowed to ask at most $\mathbf{25}$ queries.

This is an interactive problem.

"Everybody! Doremy's Perfect Data Structure Class is about to start! Come and do your best if you want to have as much IQ as me!" In today's Data Structure class, Doremy is teaching everyone a powerful data structure — Doremy tree! Now she gives you a quiz to prove that you are paying attention in class.

Given an array $a$ of length $m$, Doremy tree supports the query $Q(l,r,k)$, where $1 \leq l \leq r \leq m$ and $1 \leq k \leq m$, which returns the number of distinct integers in the array $\left[\lfloor\frac{a_l}{k} \rfloor, \lfloor\frac{a_{l+1}}{k} \rfloor, \ldots, \lfloor\frac{a_r}{k} \rfloor\right]$.

Doremy has a secret permutation $p$ of integers from $1$ to $n$. You can make queries, in one query, you give $3$ integers $l,r,k$ ($1 \leq l \leq r \leq n$, $1 \leq k \leq n$) and receive the value of $Q(l,r,k)$ for the array $p$. Can you find the index $y$ ($1 \leq y \leq n$) such that $p_y=1$ in at most $\mathbf{25}$ queries?

Note that the permutation $p$ is fixed before any queries are made.

Interaction

You begin the interaction by reading an integer $n$ ($3 \le n \le 1024$) in the first line — the length of the permutation.

To make a query, you should output

* "? $l\ r\ k$" ($1 \leq l \leq r \leq n$, $1 \leq k \leq n$)

in a separate line. After each query, you should read an integer $x$ — the value of $Q(l,r,k)$ for $p$. In this version of the problem, you can make at most $25$ such queries.

To give the answer, you should output

* "! $y$" ($1 \leq y \leq n$)

in a separate line, where $p_y=1$.

After printing a query or the answer, do not forget to output the end of line and flush the output. Otherwise, you will get Idleness limit exceeded. 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.

Example

Input

```
5

2

2

1

3
```

Output

```
? 1 3 4

? 3 5 3

? 3 4 5

? 3 5 2

! 4
```

Note

The permutation in the example is $[3,5,2,1,4]$.

The input and output for example illustrate possible interaction on that test (empty lines are inserted only for clarity).

In this interaction process:

* For the first query, $\lfloor\frac{3}{4}\rfloor=0,\lfloor\frac{5}{4}\rfloor=1,\lfloor\frac{2}{4}\rfloor=0$, so the answer is $2$.
* For the second query, $\lfloor\frac{2}{3}\rfloor=0,\lfloor\frac{1}{3}\rfloor=0,\lfloor\frac{4}{3}\rfloor=1$, so the answer is still $2$.
* For the third query, $\lfloor\frac{2}{5}\rfloor=0,\lfloor\frac{1}{5}\rfloor=0$, so the answer is $1$.
* For the fourth query, $\lfloor\frac{2}{2}\rfloor=1,\lfloor\frac{1}{2}\rfloor=0,\lfloor\frac{4}{2}\rfloor=2$, so the answer is $3$.

The correct answer is got after $4$ queries, so this process will be judged correct.

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

using namespace std;



static long long queries = 0;

static const long long query_limit = 25;


static const long long HARD_CAP = 1000;


static int n;
static vector<int> p;




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());
}

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

    
    
    n = inf.readInt(3, 1024, "n");
    p.resize(n);
    vector<bool> seen(n + 1, false);
    for (int i = 0; i < n; i++) {
        p[i] = inf.readInt(1, n, format("p[%d]", i + 1));
        if (seen[p[i]]) {
            quitf(_fail, "Input is not a permutation: duplicate value %d found.", p[i]);
        }
        seen[p[i]] = true;
    }

    
    
    log_metrics();

    
    cout << n << endl;
    cout.flush();

    
    while (true) {
        
        if (queries > HARD_CAP) {
            finish(_pe, format("Hard query limit (%lld) exceeded.", HARD_CAP));
        }

        
        string token;
        
        if (!(cin >> token)) {
            
            finish(_wa, "Unexpected EOF: contestant program terminated without outputting an answer.");
        }

        if (token == "!") {
            
            int y;
            if (!(cin >> y)) {
                finish(_wa, "Invalid format for answer: expected integer index after '!'.");
            }
            
            
            log_metrics();

            
            if (y < 1 || y > n) {
                finish(_wa, format("Answer index %d out of bounds [1, %d].", y, n));
            }

            
            
            if (p[y - 1] == 1) {
                finish(_ok, format("Correct! Found index %d with value 1 in %lld queries.", y, queries));
            } else {
                finish(_wa, format("Wrong answer: p[%d] = %d, expected 1.", y, p[y - 1]));
            }
            
            break;

        } else {
            
            
            int l, r, k;

            if (token == "?") {
                if (!(cin >> l >> r >> k)) {
                    finish(_wa, "Invalid query format: expected 'l r k' after '?'.");
                }
            } else {
                
                try {
                    size_t processed = 0;
                    l = stoi(token, &processed);
                    if (processed != token.size()) {
                        finish(_wa, format("Invalid token '%s': expected '?', '!', or integer.", token.c_str()));
                    }
                } catch (...) {
                    finish(_wa, format("Invalid token '%s': expected '?', '!', or integer.", token.c_str()));
                }
                if (!(cin >> r >> k)) {
                    finish(_wa, "Invalid query format: expected 'r k' after l.");
                }
            }

            
            queries++;
            
            if (queries % 5 == 0) log_metrics();

            
            if (l < 1 || l > n) finish(_wa, format("Query l=%d out of bounds [1, %d].", l, n));
            if (r < 1 || r > n) finish(_wa, format("Query r=%d out of bounds [1, %d].", r, n));
            if (k < 1 || k > n) finish(_wa, format("Query k=%d out of bounds [1, %d].", k, n));
            if (l > r) finish(_wa, format("Invalid range: l (%d) > r (%d).", l, r));

            
            static vector<int> vals;
            vals.clear();
            
            for (int i = l - 1; i < r; ++i) {
                vals.push_back(p[i] / k);
            }

            
            sort(vals.begin(), vals.end());
            int ans = 0;
            if (!vals.empty()) {
                ans = 1;
                for (size_t i = 1; i < vals.size(); ++i) {
                    if (vals[i] != vals[i - 1]) ans++;
                }
            }

            
            cout << ans << endl;
            cout.flush();
        }
    }

    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 = 25; 
static const long long HARD_CAP = 300; 


int N;
vector<int> P;


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 generate_adversarial(int n) {
    
    mt19937 rng(n * 239017); 
    
    P.resize(n);
    int split = n / 2;
    vector<int> left, right;
    
    
    if (rng() % 2) left.push_back(1);
    else right.push_back(1);
    
    
    for (int v = 2; v <= n; v += 2) {
        int v1 = v;
        int v2 = v + 1;
        if (v2 > n) {
            
            if (rng() % 2) left.push_back(v1);
            else right.push_back(v1);
        } else {
            
            
            int choice = rng() % 3;
            if (choice == 0) { 
                if (rng() % 2) { left.push_back(v1); left.push_back(v2); }
                else { right.push_back(v1); right.push_back(v2); }
            } else { 
                if (rng() % 2) { left.push_back(v1); right.push_back(v2); }
                else { left.push_back(v2); right.push_back(v1); }
            }
        }
    }
    
    
    shuffle(left.begin(), left.end(), rng);
    shuffle(right.begin(), right.end(), rng);
    
    
    while ((int)left.size() < split) {
        left.push_back(right.back());
        right.pop_back();
    }
    while ((int)left.size() > split) {
        right.push_back(left.back());
        left.pop_back();
    }
    
    
    shuffle(left.begin(), left.end(), rng);
    shuffle(right.begin(), right.end(), rng);
    
    
    for(int i=0; i<(int)left.size(); ++i) P[i] = left[i];
    for(int i=0; i<(int)right.size(); ++i) P[split + i] = right[i];
}


int query_val(int l, int r, int k) {
    
    set<int> distinct;
    for (int i = l - 1; i < r; i++) {
        distinct.insert(P[i] / k); 
    }
    return (int)distinct.size();
}

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

    
    N = inf.readInt(3, 1024, "n");
    
    
    
    
    if (!inf.seekEof()) {
        P.resize(N);
        vector<bool> seen(N + 1, false);
        for (int i = 0; i < N; i++) {
            P[i] = inf.readInt(1, N, "p_i");
            if (seen[P[i]]) quitf(_fail, "Duplicate element in permutation");
            seen[P[i]] = true;
        }
    } else {
        generate_adversarial(N);
    }

    
    cout << N << endl;
    
    
    while (true) {
        string type;
        if (!(cin >> type)) {
            finish(_pe, "Unexpected EOF reading query type");
        }
        
        if (type == "!") {
            int y;
            if (!(cin >> y)) finish(_pe, "Expected answer index y");
            
            
            if (y < 1 || y > N) finish(_pe, "Answer index out of range [1, N]");
            
            log_metrics(); 
            
            
            if (P[y-1] == 1) {
                finish(_ok, "Correct");
            } else {
                finish(_wa, "Wrong answer: p[y] != 1");
            }
        } else if (type == "?") {
            int l, r, k;
            if (!(cin >> l >> r >> k)) finish(_pe, "Expected arguments l r k");
            
            
            if (l < 1 || r > N || l > r) finish(_pe, "Invalid range [l, r]");
            if (k < 1 || k > N) finish(_pe, "Invalid k");
            
            queries++;
            
            
            if (queries > HARD_CAP) {
                finish(_pe, "Too many queries (hard cap exceeded)");
            }
            
            
            if (queries % 10 == 0) log_metrics();
            
            int ans = query_val(l, r, k);
            cout << ans << endl;
        } else {
            finish(_pe, "Unknown query type (expected '?' or '!')");
        }
    }
    
    return 0;
}


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

using namespace std;

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

    
    string mode = opt<string>("mode", "non");
    int seed_val = atoi(argv[1]);

    int n;
    
    
    if (seed_val == 1) n = 3;
    else if (seed_val == 2) n = 1024;
    else if (seed_val == 3) n = 4; 
    else {
        
        int t = rnd.next(3);
        if (t == 0) {
            
            n = rnd.next(3, 1024);
        } else if (t == 1) {
            
            n = 1 << rnd.next(2, 10);
        } else {
            
            n = (1 << rnd.next(2, 10)) + rnd.next(-2, 2);
            n = max(3, min(1024, n));
        }
    }

    
    if (mode == "adp") {
        cout << n << endl;
        return 0;
    }

    
    vector<int> p(n);
    
    
    
    
    
    bool adversarial = (seed_val > 5 && seed_val % 2 == 0);

    if (!adversarial) {
        iota(p.begin(), p.end(), 1);
        shuffle(p.begin(), p.end());
    } else {
        int split = n / 2;
        vector<int> left, right;
        
        
        if (rnd.next(2)) left.push_back(1);
        else right.push_back(1);

        int max_val = n;
        
        for (int v = 2; v <= max_val; v += 2) {
            int v1 = v;
            int v2 = v + 1;
            if (v2 > max_val) {
                
                if (rnd.next(2)) left.push_back(v1);
                else right.push_back(v1);
            } else {
                
                
                if (rnd.next(3)) { 
                    if (rnd.next(2)) { left.push_back(v1); right.push_back(v2); }
                    else { left.push_back(v2); right.push_back(v1); }
                } else { 
                    if (rnd.next(2)) { left.push_back(v1); left.push_back(v2); }
                    else { right.push_back(v1); right.push_back(v2); }
                }
            }
        }
        
        
        shuffle(left.begin(), left.end());
        shuffle(right.begin(), right.end());

        
        while ((int)left.size() < split) {
            left.push_back(right.back());
            right.pop_back();
        }
        while ((int)left.size() > split) {
            right.push_back(left.back());
            left.pop_back();
        }
        
        
        shuffle(left.begin(), left.end());
        shuffle(right.begin(), right.end());

        
        for(int i=0; i<(int)left.size(); ++i) p[i] = left[i];
        for(int i=0; i<(int)right.size(); ++i) p[split + i] = right[i];
    }

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

    return 0;
}