Problem: cf809_b
Difficulty: medium
Categories: search
Time limit: 2000 ms, memory limit: 256 MB

B. Glad to see you!

This is an interactive problem. In the output section below you will see the information about flushing the output.

On Sunday Leha the hacker took Nura from the house where she lives and went with her to one of the most luxurious restaurants in Vičkopolis. Upon arrival, they left the car in a huge parking lot near the restaurant and hurried inside the building.

In the restaurant a polite waiter immediately brought the menu to Leha and Noora, consisting of *n* dishes. It is interesting that all dishes in the menu are numbered with integers from 1 to *n*. After a little thought, the girl ordered exactly *k* different dishes from available in the menu. To pass the waiting time while the chefs prepare ordered dishes, the girl invited the hacker to play a game that will help them get to know each other better.

The game itself is very simple: Noora wants Leha to guess any two dishes among all ordered. At the same time, she is ready to answer only one type of questions. Leha can say two numbers *x* and *y* (1 ≤ *x*, *y* ≤ *n*). After that Noora chooses some dish *a* for the number *x* such that, at first, *a* is among the dishes Noora ordered (*x* can be equal to *a*), and, secondly, the value ![](https://espresso.codeforces.com/e5a4a1705bc256e413564795cc8b70857f0ae44c.png) is the minimum possible. By the same rules the girl chooses dish *b* for *y*. After that Noora says «TAK» to Leha, if ![](https://espresso.codeforces.com/a65cb6a9b614699e12e529560e2d39ffa39127db.png), and «NIE» otherwise. However, the restaurant is preparing quickly, so Leha has enough time to ask no more than 60 questions. After that he should name numbers of any two dishes Noora ordered.

Help Leha to solve this problem!

Input

There are two numbers *n* and *k* (2 ≤ *k* ≤ *n* ≤ 105) in the single line of input denoting the number of dishes in the menu and the number of dishes Noora ordered.

Output

If you want to provide an answer, output a string of the form 2 *x* *y* (1 ≤ *x*, *y* ≤ *n*, *x* ≠ *y*), if you think the dishes *x* and *y* was among dishes ordered by Noora. After that, flush the output and terminate your program.

Interaction

While helping Leha, you can ask queries to Noora no more than 60 times. Each query should be printed in it's own line and have the form 1 *x* *y* (1 ≤ *x*, *y* ≤ *n*). You have to both print the end-of-line character and flush the output. After flushing you should read the answer for this query from input.

After each query jury's program will print one line «TAK» or «NIE» (without quotes) in input stream depending on the girl's answer.

To flush you can use (just after printing an integer and end-of-line):

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

Example

Input

```
3 2  
NIE  
TAK  
NIE  
TAK  
TAK  
TAK
```

Output

```
1 1 2  
1 2 1  
1 1 3  
1 3 1  
1 2 3  
1 3 2  
2 2 3
```

Note

There are three dishes in sample. Noora ordered dished numberes 2 and 3, which Leha should guess. If Noora receive requests for the first dish (*x* = 1), then she'll choose the second dish (*a* = 2) as the dish with the minimum value ![](https://espresso.codeforces.com/e5a4a1705bc256e413564795cc8b70857f0ae44c.png). For the second (*x* = 2) and the third (*x* = 3) dishes themselves will be optimal, because in that case ![](https://espresso.codeforces.com/79add195d023131e992b60a354fec89501759e75.png).

Let Leha asks Noora about the next couple of dishes:

* *x* = 1, *y* = 2, then he'll recieve «NIE» answer, because |1 - 2| > |2 - 2|
* *x* = 2, *y* = 1, then he'll recieve «TAK» answer, because |2 - 2| ≤ |1 - 2|
* *x* = 1, *y* = 3, then he'll recieve «NIE» answer, because |1 - 2| > |3 - 3|
* *x* = 3, *y* = 1, then he'll recieve «TAK» answer, because |3 - 3| ≤ |1 - 2|
* *x* = 2, *y* = 3, then he'll recieve «TAK» answer, because |2 - 2| ≤ |3 - 3|
* *x* = 3, *y* = 2, then he'll recieve «TAK» answer, because |3 - 3| ≤ |2 - 2|

According to the available information, it is possible to say that Nura ordered dishes with numbers 2 and 3.

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

using namespace std;


static const long long QUERY_LIMIT = 60;

static const long long HARD_QUERY_CAP = 2000;


static long long queries = 0;
static long long query_limit = QUERY_LIMIT;
static bool finished_mode = false;


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


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


static void final_log() {
    if (!finished_mode) {
        log_metrics();
    }
}


int get_min_dist(int p, const vector<int>& s) {
    auto it = lower_bound(s.begin(), s.end(), p);
    int d = 2000000000; 
    
    
    if (it != s.end()) {
        d = min(d, abs(p - *it));
    }
    
    if (it != s.begin()) {
        d = min(d, abs(p - *prev(it)));
    }
    return d;
}

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

    
    
    int n = inf.readInt();
    int k = inf.readInt();
    
    vector<int> s(k);
    for (int i = 0; i < k; ++i) {
        s[i] = inf.readInt();
    }
    
    sort(s.begin(), s.end());

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

    
    while (true) {
        string token;
        
        if (!(cin >> token)) {
            
            finish(_wa, "Unexpected EOF: expected query ('1'/'?') or answer ('2'/'!')");
        }

        
        
        
        
        
        bool is_query = (token == "1" || token == "?");
        bool is_answer = (token == "2" || token == "!");

        if (is_query) {
            int x, y;
            if (!(cin >> x >> y)) {
                finish(_wa, "Malformed query parameters: expected 2 integers");
            }

            
            if (x < 1 || x > n || y < 1 || y > n) {
                finish(_pe, format("Query coordinates out of bounds: x=%d, y=%d, n=%d", x, y, n));
            }

            
            queries++;
            if (queries > HARD_QUERY_CAP) {
                finish(_pe, "Hard query limit exceeded (> 2000)");
            }
            
            if (queries % 10 == 0) {
                log_metrics();
            }

            
            int dist_x = get_min_dist(x, s);
            int dist_y = get_min_dist(y, s);

            
            if (dist_x <= dist_y) {
                cout << "TAK" << endl;
            } else {
                cout << "NIE" << endl;
            }

        } else if (is_answer) {
            int x, y;
            if (!(cin >> x >> y)) {
                finish(_wa, "Malformed answer parameters: expected 2 integers");
            }

            
            bool x_in_s = binary_search(s.begin(), s.end(), x);
            bool y_in_s = binary_search(s.begin(), s.end(), y);

            if (x != y && x_in_s && y_in_s) {
                finish(_ok, format("Correct! Found %d and %d. queries=%lld", x, y, queries));
            } else {
                string msg = "Incorrect answer. ";
                if (x == y) msg += format("x and y must be distinct (got %d). ", x);
                if (!x_in_s) msg += format("Dish %d is not in the hidden set. ", x);
                if (!y_in_s) msg += format("Dish %d is not in the hidden set. ", y);
                finish(_wa, msg);
            }

        } else {
            
            finish(_pe, format("Protocol error: expected '1', '2', '?', or '!', but got '%s'", token.c_str()));
        }
    }

    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 = 60; 


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 n, k;

vector<vector<int>> candidates;


long long get_dist(int p, const vector<int>& S) {
    auto it = lower_bound(S.begin(), S.end(), p);
    long long d = 2000000000LL; 
    if (it != S.end()) {
        d = min(d, (long long)(*it) - p);
    }
    if (it != S.begin()) {
        d = min(d, (long long)p - *prev(it));
    }
    return d;
}


bool eval_query(const vector<int>& S, int x, int y) {
    long long dx = get_dist(x, S);
    long long dy = get_dist(y, S);
    return dx <= dy;
}

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

    
    n = inf.readInt(2, 100000, "n");
    k = inf.readInt(2, n, "k");

    
    cout << n << " " << k << endl;

    
    
    inf.skipBlanks();
    if (!inf.eof()) {
        
        vector<int> S(k);
        for(int i=0; i<k; ++i) S[i] = inf.readInt(1, n, "s_i");
        sort(S.begin(), S.end());
        candidates.push_back(S);
    } else {
        
        
        mt19937 rng(n * 239 + k * 17 + 58);
        
        
        int max_candidates = 1000;
        if (n > 5000) max_candidates = 300;
        if (n > 50000) max_candidates = 100;

        
        auto add_cand = [&](vector<int> s) {
            sort(s.begin(), s.end());
            s.erase(unique(s.begin(), s.end()), s.end());
            
            
            if ((int)s.size() < k) {
                
                
                vector<bool> present(n + 1, false);
                for(int x : s) present[x] = true;
                for(int i=1; i<=n && (int)s.size() < k; ++i) {
                    if(!present[i]) {
                        s.push_back(i);
                        present[i] = true;
                    }
                }
                sort(s.begin(), s.end());
            }
            candidates.push_back(s);
        };

        
        
        
        {
            vector<int> s;
            for(int i=1; i<=k; ++i) s.push_back(i);
            add_cand(s);
        }
        
        
        {
            vector<int> s;
            for(int i=0; i<k; ++i) s.push_back(n-i);
            add_cand(s);
        }
        
        
        if (k >= 2) {
             vector<int> s;
             s.push_back(1); s.push_back(n);
             while((int)s.size() < k) s.push_back(rng() % n + 1);
             add_cand(s);
        }
        
        
        {
            vector<int> s;
            int start = max(1, n/2 - k/2);
            for(int i=0; i<k; ++i) if(start+i <= n) s.push_back(start+i);
            add_cand(s);
        }

        
        while ((int)candidates.size() < max_candidates) {
             vector<int> s;
             if (k * 2 < n) {
                 
                 while((int)s.size() < k) s.push_back(rng() % n + 1);
             } else {
                 
                 vector<int> excl;
                 while((int)excl.size() < n - k) excl.push_back(rng() % n + 1);
                 sort(excl.begin(), excl.end());
                 excl.erase(unique(excl.begin(), excl.end()), excl.end());
                 
                 
                 int ptr = 0;
                 for(int i=1; i<=n; ++i) {
                     if(ptr < (int)excl.size() && excl[ptr] == i) {
                         ptr++;
                     } else {
                         s.push_back(i);
                     }
                 }
                 
                 if((int)s.size() > k) s.resize(k);
             }
             add_cand(s);
        }
    }

    
    while (true) {
        
        if (queries > max(200000LL, 10 * query_limit)) {
            finish(_pe, "Too many queries (hard cap exceeded)");
        }

        
        string type;
        cin >> type;
        if (cin.fail()) finish(_pe, "Unexpected EOF while reading query type");

        bool is_ans = (type == "2" || type == "!");
        if (!is_ans && type != "1" && type != "?") {
            finish(_pe, format("Invalid query type: '%s'. Expected '1' or '2'.", type.c_str()));
        }

        int x, y;
        cin >> x >> y;
        if (cin.fail()) finish(_pe, "Unexpected EOF while reading query arguments");

        
        if (x < 1 || x > n || y < 1 || y > n) {
            finish(_wa, format("Arguments out of range: %d %d", x, y));
        }
        if (is_ans && x == y) {
            finish(_wa, format("Final answer must contain distinct dishes, got: %d %d", x, y));
        }

        if (is_ans) {
            
            
            
            
            for (const auto& S : candidates) {
                bool has_x = binary_search(S.begin(), S.end(), x);
                bool has_y = binary_search(S.begin(), S.end(), y);
                if (!has_x || !has_y) {
                    finish(_wa, format("Wrong Answer: guess {%d, %d} is incorrect for a consistent hidden set", x, y));
                }
            }
            
            finish(_ok, format("Correct! Found dishes {%d, %d}", x, y));
        } else {
            
            queries++;
            
            int votes_tak = 0;
            int votes_nie = 0;
            for (const auto& S : candidates) {
                if (eval_query(S, x, y)) votes_tak++;
                else votes_nie++;
            }

            
            
            bool ans_tak = (votes_tak >= votes_nie);
            cout << (ans_tak ? "TAK" : "NIE") << endl;

            
            int head = 0;
            for (int i = 0; i < (int)candidates.size(); ++i) {
                if (eval_query(candidates[i], x, y) == ans_tak) {
                    if (head != i) candidates[head] = move(candidates[i]);
                    head++;
                }
            }
            candidates.resize(head);

            if (candidates.empty()) {
                
                finish(_wa, "Interactor Error: No consistent hidden sets left.");
            }
        }
    }
}


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

    
    int seed_val = atoi(argv[1]);

    
    int n;
    if (n_opt != -1) {
        n = n_opt;
    } else {
        if (seed_val == 1) n = 3;                  
        else if (seed_val == 2) n = 10;            
        else if (seed_val == 3) n = 100000;        
        else if (seed_val <= 10) n = rnd.next(10, 100);
        else n = rnd.next(90000, 100000);          
    }

    
    int k;
    if (k_opt != -1) {
        k = k_opt;
    } else {
        if (seed_val == 1) k = 2;
        else if (seed_val == 2) k = 5;
        else if (seed_val == 3) k = 2;
        else if (seed_val == 4) k = n; 
        else {
            int type = rnd.next(1, 100);
            if (type <= 30) k = 2;                           
            else if (type <= 50) k = min(n, rnd.next(3, 20)); 
            else if (type <= 80) k = rnd.next(2, n);          
            else k = rnd.next(max(2, n - 50), n);             
        }
    }

    
    n = max(2, min(n, 100000));
    k = max(2, min(k, n));

    
    cout << n << " " << k << endl;

    
    if (mode == "non") {
        
        vector<int> s;
        
        
        bool pattern_used = false;
        
        
        if (!pattern_used && seed_val == 3 && k == 2) {
            s = {1, n};
            pattern_used = true;
        }
        
        
        if (!pattern_used && seed_val == 5 && k == 2) {
            if (n >= 2) {
                s = {n / 2, n / 2 + 1};
                pattern_used = true;
            }
        }

        
        if (!pattern_used && seed_val == 6 && k == 2) {
            s = {1, 2};
            pattern_used = true;
        }

        
        if (!pattern_used) {
            
            s = rnd.distinct(k, n);
            for (int &x : s) x++; 
        }

        sort(s.begin(), s.end());
        println(s);
    } else {
        
        
        
    }

    return 0;
}