Problem: cf1697_d
Difficulty: hard
Categories: search
Time limit: 4000 ms, memory limit: 512 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].

The jury has chosen a string $s$ consisting of $n$ characters; each character of $s$ is a lowercase Latin letter. Your task is to guess this string; initially, you know only its length.

You may ask queries of two types:

* $1$ $i$ — the query of the first type, where $i$ is an integer from $1$ to $n$. In response to this query, the jury will tell you the character $s_i$;
* $2$ $l$ $r$ — the query of the second type, where $l$ and $r$ are integers such that $1 \le l \le r \le n$. In response to this query, the jury will tell you the number of different characters among $s_l, s_{l+1}, \dots, s_r$.

You are allowed to ask no more than $26$ queries of the first type, and no more than $6000$ queries of the second type. Your task is to restore the string $s$.

For each test in this problem, the string $s$ is fixed beforehand, and will be the same for every submission.

Input

Initially, the jury program sends one integer $n$ on a separate line — the size of $s$ ($1 \le n \le 1000$).

Output

To give the answer, print one line! s with a line break in the end, where $s$ should be the string picked by the jury. After that, your program should flush the output and terminate gracefully.

Interaction

To ask a query, you should send one line containing the query, in one of the following formats:

*? 1 i — for a query of the first type ($1 \le i \le n$);
*? 2 l r — for a query of the second type ($1 \le l \le r \le n$).

Don't forget to flush the output after sending the query line.

The answer to your query will be given on a separate line. For a query of the first type, the answer will be the character $s_i$. For a query of the second type, the answer will be an integer equal to the number of different characters among $s_l, s_{l+1}, \dots, s_r$.

You are allowed to ask no more than $26$ queries of the first type, and no more than $6000$ queries of the second type.

In case you ask too many queries, or the jury program fails to recognize your query format, the answer to your query will be one integer $0$. After receiving $0$ as the answer, your program should terminate immediately — otherwise you may receive verdict "Runtime error", "Time limit exceeded" or some other verdict instead of "Wrong answer".

Example

Input

```
5
4
u
2
g
e
s
1
```

Output

```? 2 1 5? 1 2? 2 1 2? 1 1? 1 3? 1 4? 2 4 5! guess
```

Note

Let's analyze the example of interaction.

The string chosen by the jury is guess, so initially the jury sends one integer $5$.

1. the first query is? 2 1 5, which means "count the number of different characters among $s_1, s_2, \dots, s_5$". The answer to it is $4$.
2. the second query is? 1 2, which means "tell which character is $s_2$". The answer to it is u.
3. the third query is? 2 1 2, which means "count the number of different characters among $s_1$ and $s_2$". The answer to it is $2$.
4. the fourth query is? 1 1, which means "tell which character is $s_1$". The answer to it is g.
5. the fifth query is? 1 3, which means "tell which character is $s_3$". The answer to it is e.
6. the sixth query is? 1 4, which means "tell which character is $s_4$". The answer to it is s.
7. the seventh query is? 2 4 5, which means "count the number of different characters among $s_4$ and $s_5$". The answer to it is $1$, so it's possible to deduce that $s_4$ is the same as $s_5$.

In the end, the answer is submitted as! guess, and it is deduced correctly.

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

using namespace std;


const int LIMIT_TYPE_1 = 26;
const int LIMIT_TYPE_2 = 6000;

const int TOTAL_LIMIT = LIMIT_TYPE_1 + LIMIT_TYPE_2;


static long long queries = 0;
static long long cnt1 = 0;
static long long cnt2 = 0;
static long long query_limit = TOTAL_LIMIT; 


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

    
    
    string s = inf.readToken();
    int n = (int)s.length();
    
    
    cout << n << endl;
    
    
    log_metrics();

    while (true) {
        
        if (queries > 200000) {
            finish(_pe, "Hard query limit exceeded (potential infinite loop)");
        }

        string token;
        
        if (!(cin >> token)) {
            finish(_wa, "Unexpected EOF (no answer submitted)");
        }

        
        if (!token.empty() && token[0] == '!') {
            string guess;
            if (token == "!") {
                
                if (!(cin >> guess)) {
                    finish(_wa, "EOF after '!'");
                }
            } else {
                
                guess = token.substr(1);
            }
            
            if (guess == s) {
                finish(_ok, "Correct string restored");
            } else {
                finish(_wa, ("Incorrect answer. Expected: " + s + ", Found: " + guess).c_str());
            }
        }

        
        
        int type = -1;
        if (token == "?") {
            if (!(cin >> type)) {
                finish(_wa, "EOF after '?'");
            }
        } else {
            try {
                size_t pos;
                type = stoi(token, &pos);
                if (pos != token.size()) {
                     finish(_pe, ("Invalid token (garbage): " + token).c_str());
                }
            } catch (...) {
                finish(_pe, ("Invalid token (not a number): " + token).c_str());
            }
        }

        
        if (type == 1) {
            int i;
            if (!(cin >> i)) finish(_wa, "EOF reading query 1 parameter");
            
            
            if (i < 1 || i > n) {
                finish(_pe, format("Query 1: index %d out of bounds [1, %d]", i, n).c_str());
            }

            
            cnt1++;
            queries++;
            
            
            if (cnt1 > LIMIT_TYPE_1) {
                finish(_wa, format("Too many queries of type 1 (%lld > %d)", cnt1, LIMIT_TYPE_1).c_str());
            }
            
            
            cout << s[i-1] << endl;

        } else if (type == 2) {
            int l, r;
            if (!(cin >> l >> r)) finish(_wa, "EOF reading query 2 parameters");
            
            
            if (l < 1 || l > n || r < 1 || r > n || l > r) {
                finish(_pe, format("Query 2: invalid range [%d, %d] for n=%d", l, r, n).c_str());
            }
            
            
            cnt2++;
            queries++;
            
            
            if (cnt2 > LIMIT_TYPE_2) {
                finish(_wa, format("Too many queries of type 2 (%lld > %d)", cnt2, LIMIT_TYPE_2).c_str());
            }

            
            int mask = 0; 
            for (int k = l - 1; k < r; k++) {
                mask |= (1 << (s[k] - 'a'));
            }
            int distinct = __builtin_popcount(mask);
            
            
            cout << distinct << endl;

        } else {
            finish(_pe, format("Unknown query type: %d", type).c_str());
        }
        
        
        if (queries % 10 == 0) {
            log_metrics();
        }
    }

    return 0;
}


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

using namespace std;


static const int MAX_Q1 = 26;
static const int MAX_Q2 = 6000;


static const int QUERY_LIMIT = MAX_Q1 + MAX_Q2; 

static int q1_count = 0;
static int q2_count = 0;


static void log_metrics() {
    try {
        long long total_queries = (long long)q1_count + q2_count;
        
        
        
        
        if (q1_count > MAX_Q1 || q2_count > MAX_Q2) {
            if (total_queries <= QUERY_LIMIT) {
                total_queries = (long long)QUERY_LIMIT + 1;
            }
        }
        
        tout << "queries=" << total_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);

    string s;
    int n;

    
    
    
    string token = inf.readToken();
    if (token.empty()) {
        finish(_fail, "Input file is empty");
    }

    bool is_number = true;
    for (char c : token) {
        if (!isdigit(c)) {
            is_number = false;
            break;
        }
    }

    if (is_number) {
        
        
        n = stoi(token);
        
        
        
        mt19937 rng(n * 239017 + 777);
        s.resize(n);

        if (n < 26) {
            
            for (int i = 0; i < n; ++i) {
                s[i] = 'a' + (rng() % 26);
            }
        } else {
            
            vector<char> chars(26);
            iota(chars.begin(), chars.end(), 'a');
            shuffle(chars.begin(), chars.end(), rng);

            
            for (int i = 0; i < 26; ++i) s[i] = chars[i];
            
            for (int i = 26; i < n; ++i) s[i] = 'a' + (rng() % 26);
            
            
            shuffle(s.begin(), s.end(), rng);
        }
    } else {
        
        s = token;
        n = s.size();
    }

    
    cout << n << endl;
    
    log_metrics();

    
    int hard_cap = 200000;

    
    while (true) {
        string typeStr;
        
        if (!(cin >> typeStr)) {
            
            finish(_wa, "Unexpected EOF (expected '?' or '!')");
        }

        if (typeStr == "!") {
            string ans;
            if (!(cin >> ans)) {
                finish(_pe, "Expected answer string after '!'");
            }
            
            if (ans == s) {
                finish(_ok, "Correct");
            } else {
                finish(_wa, "Wrong answer: expected " + s + ", got " + ans);
            }
        } else if (typeStr == "?") {
            
            if (q1_count + q2_count > hard_cap) {
                finish(_pe, "Hard query limit exceeded");
            }

            int type;
            if (!(cin >> type)) finish(_pe, "Expected query type (1 or 2) after '?'");

            if (type == 1) {
                int i;
                if (!(cin >> i)) finish(_pe, "Expected index i for query 1");
                if (i < 1 || i > n) finish(_pe, "Index out of bounds");
                
                q1_count++;
                cout << s[i-1] << endl;
            } else if (type == 2) {
                int l, r;
                if (!(cin >> l >> r)) finish(_pe, "Expected l r for query 2");
                if (l < 1 || r > n || l > r) finish(_pe, "Invalid range [l, r]");

                q2_count++;
                
                int mask = 0;
                for (int k = l - 1; k < r; ++k) {
                    mask |= (1 << (s[k] - 'a'));
                }
                cout << __builtin_popcount(mask) << endl;
            } else {
                finish(_pe, "Unknown query type: " + to_string(type));
            }

            
            if ((q1_count + q2_count) % 50 == 0) {
                log_metrics();
            }
        } else {
            finish(_pe, "Protocol error: expected '?' or '!', got '" + typeStr + "'");
        }
    }

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

    long long seed_val = -1;
    
    if (argc > 1) {
        try {
            seed_val = stoll(argv[1]);
        } catch (...) {
            seed_val = -1;
        }
    }

    
    int n = 1000;
    if (n_arg != -1) {
        n = n_arg;
    } else {
        
        if (seed_val == 1) n = 1;
        else if (seed_val == 2) n = 26;
        else if (seed_val == 3) n = 1000;
        else if (seed_val == 4) n = 1000;
        else if (seed_val > 0 && seed_val <= 10) n = rnd.next(1, 100);
        else n = rnd.next(900, 1000); 
    }
    
    
    string s = "";
    
    if (seed_val == 1) {
        s = "a";
    } else if (seed_val == 2) {
        
        for (int i = 0; i < 26; ++i) s += (char)('a' + i);
    } else if (seed_val == 3) {
        
        s = string(n, 'a');
    } else if (seed_val == 4) {
        
        for (int i = 0; i < n; ++i) s += (i % 2 == 0 ? 'a' : 'b');
    } else {
        
        int type = rnd.next(5);
        if (type == 0) {
            
            for (int i = 0; i < n; ++i) s += (char)('a' + rnd.next(26));
        } else if (type == 1) {
            
            vector<char> p(26);
            iota(p.begin(), p.end(), 'a');
            shuffle(p.begin(), p.end());
            for (int i = 0; i < n; ++i) {
                int idx = 0;
                
                while (idx < 25 && rnd.next(3) == 0) idx++;
                s += p[idx];
            }
        } else if (type == 2) {
            
            while ((int)s.size() < n) {
                char c = (char)('a' + rnd.next(26));
                int len = rnd.next(1, 50);
                for (int k = 0; k < len && (int)s.size() < n; ++k) s += c;
            }
        } else if (type == 3) {
            
            vector<char> p(26);
            iota(p.begin(), p.end(), 'a');
            shuffle(p.begin(), p.end());
            for (char c : p) s += c;
            while ((int)s.size() < n) s += p[rnd.next(26)];
            shuffle(s.begin(), s.end());
        } else {
            
            int period = rnd.next(1, 20);
            string pat = "";
            for(int k=0; k<period; ++k) pat += (char)('a' + rnd.next(26));
            for(int i=0; i < n; ++i) s += pat[i % period];
        }
    }

    
    if ((int)s.size() > n) s.resize(n);
    while ((int)s.size() < n) s += (char)('a' + rnd.next(26));

    
    if (mode == "non") {
        
        cout << s << endl;
    } else if (mode == "adp") {
        
        cout << n << endl;
    } else {
        quitf(_fail, "Unknown mode: %s", mode.c_str());
    }

    return 0;
}