Problem: cf1924_f
Difficulty: hard
Categories: data structures, search
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive problem!

Mr. 1048576 is one of those faculty who hates wasting his time in taking class attendance. Instead of taking attendance the old-fashioned way, he decided to try out something new today.

There are $n$ students in his class, having roll numbers $1$ to $n$. He knows that exactly $1$ student is absent today. In order to determine who is absent, he can ask some queries to the class. In each query, he can provide two integers $l$ and $r$ ($1\leq l\leq r\leq n$) and all students whose roll numbers are between $l$ and $r$ (inclusive) will raise their hands. He then counts them to determine if the roll number of the absent student lies between these values.

Things seemed fine until his teaching assistant noticed something — the students are dishonest! Some students whose roll numbers lie in the given range may not raise their hands, while some other students whose roll number does not lie in the given range may raise their hands. But the students don't want to raise much suspicion. So, only the following $4$ cases are possible for a particular query $(l,r)$ —

1. True Positive: $r-l+1$ students are present and $r-l+1$ students raised their hands.
2. True Negative: $r-l$ students are present and $r-l$ students raised their hands.
3. False Positive: $r-l$ students are present but $r-l+1$ students raised their hands.
4. False Negative: $r-l+1$ students are present but $r-l$ students raised their hands.

In the first two cases, the students are said to be answering honestly, while in the last two cases, the students are said to be answering dishonestly. The students can mutually decide upon their strategy, not known to Mr. 1048576. Also, the students do not want to raise any suspicion and at the same time, want to create a lot of confusion. So, their strategy always meets the following two conditions —

1. The students will never answer honestly $3$ times in a row.
2. The students will never answer dishonestly $3$ times in a row.

Mr. 1048576 is frustrated by this act of students. So, he is willing to mark at most $2$ students as absent (though he knows that only one is). The attendance is said to be successful if the student who is actually absent is among those two. Also, due to limited class time, he can only ask up to $\lceil\log_{1.116}{n}\rceil-1$ queries (weird numbers but okay). Help him complete a successful attendance.

Interaction

First read a line containing a single integer $t$ ($1\leq t\leq 2048$) denoting the number of independent test cases that you must solve.

For each test case, first read a line containing a single integer $n$ ($3\leq n\leq 10^5$). Then you may ask up to $\lceil\log_{1.116}{n}\rceil-1$ queries.

To ask a query, print a single line in the format "? l r" (without quotes) $(1\leq l\leq r\leq n)$. Then read a single line containing a single integer $x$ ($r-l\leq x\leq r-l+1$) denoting the number of students who raised their hands corresponding to the query.

To mark a student as absent, print a single line in the format "! a" (without quotes) $(1\leq a\leq n)$. Then read a single integer $y$ ($y\in\{0,1\}$). If the student with roll number $a$ was absent, $y=1$, else, $y=0$. Note that this operation does not count as a query but you can do this operation at most $2$ times.

To end a test case, print a single line in the format "#" (without quotes). Then you must continue solving the remaining test cases.

If you ask more queries than allowed or ask an invalid query, you will get the Wrong answer verdict.

It is guaranteed that the sum of $n$ over all test cases does not exceed $10^5$.

After printing the answers, do not forget to output end of line and flush the output buffer. Otherwise, you will get the verdict Idleness limit exceeded. To flush the buffer, use:

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

Note that the grader for this problem is adaptive meaning that the answer may change depending on your queries but will always remain consistent with the constraints and the answer to the previous queries.

Example

Input

```
2
5

3

2

1

2

0

1

0

2

0

1

6

6

2

2

0

1

1

0

0

0

1
```

Output

```
? 1 4

? 3 5

? 2 2

? 1 3

? 3 3

? 3 3

! 3

? 2 4

? 4 4

! 2

#

? 1 6

? 1 3

? 4 6

? 1 1

? 3 3

? 5 5

! 3

? 2 2

? 4 4

! 4

#
```

Note

For the first test case, the student with roll number $2$ is absent and the truth sequence is TFFTFTTF. During execution of your solution, this test case will use a non-adaptive grader.

For the second test case, the student with roll number $4$ is absent, and the truth sequence is FFTFTTFT. During the execution of your solution, in this test case your program will interact with an adaptive grader. So, the actual answer might be different depending on your queries but will always remain consistent with the responses to the previous queries.

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


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


static bool found = false;
static int guesses_used = 0;


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



struct DeterministicGen {
    mt19937 rng;
    DeterministicGen(int seed) : rng(seed) {}
    int next(int low, int high) {
        return uniform_int_distribution<int>(low, high)(rng);
    }
};

void solve_test_case() {
    
    int n = inf.readInt();
    
    
    string mode = inf.readToken();
    
    int x;       
    string s;    
    
    if (mode == "fixed") {
        x = inf.readInt();
        s = inf.readToken();
    } else {
        
        
        DeterministicGen gen(n * 1337 + 7);
        x = gen.next(1, n);
        
        int len = 400; 
        s = "";
        for (int i = 0; i < len; ++i) {
            vector<char> choices;
            
            bool canT = true;
            if (i >= 2 && s[i-1] == 'T' && s[i-2] == 'T') canT = false;
            
            bool canF = true;
            if (i >= 2 && s[i-1] == 'F' && s[i-2] == 'F') canF = false;
            
            if (canT) choices.push_back('T');
            if (canF) choices.push_back('F');
            
            s += choices[gen.next(0, choices.size() - 1)];
        }
    }

    
    double limit_val = ceil(log(n) / log(1.116)) - 1;
    long long limit = (long long)max(0.0, limit_val);
    query_limit += limit;
    
    
    log_metrics();

    
    cout << n << endl;
    
    found = false;
    guesses_used = 0;
    int query_idx = 0;

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

        string token;
        if (!(cin >> token)) {
            finish(_wa, "Unexpected EOF (did not receive '#')");
        }

        
        if (token == "#") {
            if (!found) {
                finish(_wa, "Test case ended without identifying the absent student");
            }
            return; 
        }

        
        if (token == "!") {
            int guess_a;
            if (!(cin >> guess_a)) finish(_pe, "Expected integer after '!'");
            
            guesses_used++;
            if (guesses_used > 2) {
                finish(_wa, "Too many guesses (>2)");
            }
            
            if (guess_a < 1 || guess_a > n) {
                finish(_wa, format("Invalid guess %d (n=%d)", guess_a, n));
            }
            
            
            int response = (guess_a == x ? 1 : 0);
            cout << response << endl;
            if (response == 1) found = true;
            continue;
        }

        
        int l, r;
        if (token == "?") {
            if (!(cin >> l >> r)) finish(_pe, "Expected l r after '?'");
        } else {
            
            try {
                l = stoi(token);
            } catch (...) {
                finish(_pe, "Expected integer l or command");
            }
            if (!(cin >> r)) finish(_pe, "Expected r");
        }
        
        queries++;
        
        if (l < 1 || r > n || l > r) {
            finish(_wa, format("Invalid query range [%d, %d] (n=%d)", l, r, n));
        }

        
        if (queries > 300000) { 
            finish(_pe, "Hard query limit exceeded");
        }
        
        
        
        
        int actual_count;
        if (x >= l && x <= r) {
            
            actual_count = r - l;
        } else {
            
            actual_count = r - l + 1;
        }
        
        
        char truth = 'T';
        if (query_idx < (int)s.size()) {
            truth = s[query_idx];
        } else {
            
            truth = 'T'; 
        }
        query_idx++;
        
        int reply;
        if (truth == 'T') {
            reply = actual_count;
        } else {
            
            
            
            if (actual_count == r - l) reply = r - l + 1;
            else reply = r - l;
        }
        
        cout << reply << endl;
    }
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);
    
    int t = inf.readInt();
    cout << t << endl; 
    
    for (int i = 0; i < t; ++i) {
        solve_test_case();
    }
    
    finish(_ok, "All cases passed");
    return 0;
}


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

using namespace std;


static long long total_queries = 0;
static long long total_limit = 0;
static bool interaction_failed = false; 



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


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













const int MASK_START = (1 << 4);
const int MASK_T1 = (1 << 0);
const int MASK_T2 = (1 << 1);
const int MASK_F1 = (1 << 2);
const int MASK_F2 = (1 << 3);




int next_mask_fn(int mask, char type) {
    int res = 0;
    if (type == 'T') {
        
        if (mask & MASK_START) res |= MASK_T1; 
        if (mask & MASK_T1)    res |= MASK_T2; 
        
        
        if (mask & MASK_F1)    res |= MASK_T1; 
        if (mask & MASK_F2)    res |= MASK_T1; 
    } else { 
        
        if (mask & MASK_START) res |= MASK_F1; 
        
        if (mask & MASK_T1)    res |= MASK_F1; 
        if (mask & MASK_T2)    res |= MASK_F1; 
        
        if (mask & MASK_F1)    res |= MASK_F2; 
        
    }
    return res;
}


void solve_case() {
    
    int n = inf.readInt();
    string mode = inf.readToken(); 

    
    
    double limit_val = ceil(log((double)n) / log(1.116)) - 1.0;
    long long limit = max(0LL, (long long)limit_val);
    total_limit += limit;

    
    cout << n << endl;

    
    bool is_adaptive = (mode == "adaptive");
    int fixed_x = -1;
    string fixed_s = "";
    int fixed_idx = 0;

    if (!is_adaptive) {
        if (mode == "fixed") {
            fixed_x = inf.readInt();
            fixed_s = inf.readToken();
        } else {
            
            is_adaptive = true; 
        }
    }

    
    vector<int> masks(n + 1, MASK_START);

    bool solved = false;
    
    log_metrics();

    while (true) {
        string type;
        if (!(cin >> type)) {
            finish(_pe, "Unexpected EOF while waiting for command");
        }

        if (type == "#") {
            
            break;
        }

        if (type == "!") {
            int a;
            cin >> a;
            if (a < 1 || a > n) finish(_wa, "Guess out of range");

            bool is_absent = false;

            if (!is_adaptive) {
                
                is_absent = (a == fixed_x);
            } else {
                
                
                bool can_be_other = false;
                for (int i = 1; i <= n; ++i) {
                    if (i != a && masks[i] != 0) {
                        can_be_other = true;
                        break;
                    }
                }

                if (can_be_other) {
                    is_absent = false;
                    masks[a] = 0; 
                } else {
                    
                    
                    if (masks[a] != 0) {
                        is_absent = true;
                    } else {
                        
                        is_absent = false;
                    }
                }
            }

            cout << (is_absent ? 1 : 0) << endl;
            if (is_absent) {
                solved = true;
            }
            
            

        } else if (type == "?") {
            int l, r;
            cin >> l >> r;
            if (l < 1 || r > n || l > r) finish(_wa, "Invalid query range");

            total_queries++;
            
            
            if (total_queries > 200000) finish(_pe, "Hard query limit exceeded");
            
            
            if (total_queries % 100 == 0) log_metrics();

            int ans = -1;
            
            
            

            if (!is_adaptive) {
                
                char truth = 'T';
                if (fixed_idx < (int)fixed_s.size()) {
                    truth = fixed_s[fixed_idx++];
                }
                
                bool in_range = (fixed_x >= l && fixed_x <= r);
                
                
                
                
                
                if (truth == 'T') {
                    ans = in_range ? (r - l + 1) : (r - l);
                } else {
                    ans = in_range ? (r - l) : (r - l + 1);
                }
            } else {
                
                int cnt_high = 0;
                int cnt_low = 0;

                for (int i = 1; i <= n; ++i) {
                    if (masks[i] == 0) continue;
                    
                    bool in_range = (i >= l && i <= r);
                    
                    
                    
                    
                    char t_high = in_range ? 'T' : 'F';
                    if (next_mask_fn(masks[i], t_high)) cnt_high++;

                    
                    
                    
                    char t_low = in_range ? 'F' : 'T';
                    if (next_mask_fn(masks[i], t_low)) cnt_low++;
                }

                
                if (cnt_high >= cnt_low) {
                    ans = r - l + 1;
                    
                    for (int i = 1; i <= n; ++i) {
                        if (masks[i] == 0) continue;
                        bool in_range = (i >= l && i <= r);
                        masks[i] = next_mask_fn(masks[i], in_range ? 'T' : 'F');
                    }
                } else {
                    ans = r - l;
                    
                    for (int i = 1; i <= n; ++i) {
                        if (masks[i] == 0) continue;
                        bool in_range = (i >= l && i <= r);
                        masks[i] = next_mask_fn(masks[i], in_range ? 'F' : 'T');
                    }
                }
            }
            cout << ans << endl;

        } else {
            finish(_wa, "Unknown command (expected '?', '!', or '#')");
        }
    }

    if (!solved) {
        interaction_failed = true;
    }
}

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

    
    int t = inf.readInt();
    
    
    cout << t << endl;

    for (int i = 0; i < t; ++i) {
        solve_case();
    }

    if (interaction_failed) {
        finish(_wa, "Failed to solve one or more cases");
    } else {
        finish(_ok, "All cases solved");
    }

    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 n = opt<int>("n", -1);

    
    if (n == -1) {
        int p = rnd.next(100);
        if (p < 5) {
            
            n = rnd.next(3, 10);
        } else if (p < 15) {
            
            n = rnd.next(11, 100);
        } else if (p < 30) {
            
            n = rnd.next(101, 1000);
        } else if (p < 50) {
            
            n = rnd.next(1001, 50000);
        } else if (p < 90) {
            
            n = rnd.next(90000, 99999);
        } else {
            
            n = 100000;
        }
    }

    
    cout << 1 << endl;

    if (mode == "non") {
        
        
        
        int x = rnd.next(1, n);

        
        
        int len = 300;
        string s = "";

        
        for (int i = 0; i < len; ++i) {
            vector<char> choices;
            
            bool canT = true;
            if (i >= 2 && s[i-1] == 'T' && s[i-2] == 'T') canT = false;
            
            
            bool canF = true;
            if (i >= 2 && s[i-1] == 'F' && s[i-2] == 'F') canF = false;

            if (canT) choices.push_back('T');
            if (canF) choices.push_back('F');

            
            s += choices[rnd.next(choices.size())];
        }

        cout << n << " fixed " << x << " " << s << endl;

    } else {
        
        
        
        cout << n << " adaptive" << endl;
    }

    return 0;
}