Problem: icpc2023_pacific_northwest_div2_m
Difficulty: easy
Categories: greedy, math, game
Time limit: 4000 ms, memory limit: 256 MB

You are tasked with creating a secret sequence of integers that is difficult to guess. The sequence is subject to the following constraints:

• The first number in the sequence must be 0.   
• The last number in the sequence must be 100 000.   
• Each number in the sequence must be either 1 or 2 greater than the one preceding it. At first, all you need to reveal is the length of the sequence.   
Then, an adversary will guess the numbers in the sequence one at a time.

• If the guessed number is in your sequence, you must reveal exactly where in the sequence it appears. • If the guessed number is not in your sequence, you must simply reveal that it is not in the sequence. This is considered a “miss”.

Note that because you are not forced to write down the sequence in advance, you can “cheat” by changing the sequence you have in mind, so long as it does not contradict the information you have revealed so far. It turns out that under these conditions, you can always force the adversary to get 33 333 misses before they can guess every number in your sequence. Your job is to write a program that does so.

# Interaction

This is an interactive problem.

Your program should begin by printing $k$ $2 \leq k \leq 1 0 0 0 0 1$ ), the length of your sequence, as a single integer on a single line. After this, you will receive one integer $x$ on a single line. This integer is guaranteed to be between $- 1$ and 100 000 inclusive.

• If $x = - 1$ , the adversary has given up; your program should print all $k$ integers in your sequence in order, one line per integer, and then exit. The adversary is guaranteed to give this input after it has gotten 33 333 misses, though it may do so earlier. After printing all $k$ integers, your program should exit. If you print a valid sequence consistent with your previous responses, your submission will be considered correct for this test case.

• If $x$ is not in your sequence, print $- 1$ on a single line.

• If $x$ is in your sequence, print a single integer $i$ on a single line, such that $x$ is the ith (1-indexed) number in the sequence. If you have printed every integer from 1 to $k$ , your program should now exit, and your submission will receive a Wrong Answer verdict.

Do not forget to flush the output after every integer you print.

After this, if your program has not yet exited, the process will repeat, with you receiving another single integer.   
he adversary is guaranteed to never repeat integers.

The adversary may employ different guessing strategies on different runs.

<table><tr><td rowspan="2">Read</td><td colspan="2">Sample Interaction 1</td></tr><tr><td>50001</td><td>Write</td></tr><tr><td>0</td><td></td><td></td></tr><tr><td></td><td>1</td><td></td></tr><tr><td>1</td><td></td><td></td></tr><tr><td></td><td>-1</td><td></td></tr><tr><td>-1</td><td></td><td></td></tr></table>

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 const int MISS_LIMIT = 33333;
static bool metrics_logged = false;



static void log_metrics() {
    if (metrics_logged) return;
    metrics_logged = true;
    try {
        
        if (query_limit == 0) query_limit = 100005; 
        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());
}



static bool read_int(int &val) {
    if (!(cin >> val)) return false;
    return true;
}

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

    
    
    
    int n_guesses = inf.readInt();
    vector<int> guesses;
    guesses.reserve(n_guesses);
    for (int i = 0; i < n_guesses; i++) {
        guesses.push_back(inf.readInt());
    }

    
    query_limit = n_guesses + 5; 

    
    int k;
    if (!read_int(k)) {
        finish(_pe, "Failed to read k (sequence length)");
    }
    
    if (k < 2 || k > 100001) {
        finish(_wa, format("k is out of bounds: %d", k));
    }

    
    
    
    
    
    
    vector<int> history(100001, -2);
    
    
    
    vector<bool> index_revealed(k + 1, false);
    
    int revealed_count = 0;
    int misses = 0;

    
    
    for (int x : guesses) {
        
        if (misses >= MISS_LIMIT) {
            break;
        }

        
        
        if (revealed_count == k) {
            finish(_wa, "Contestant revealed all numbers before adversary gave up");
        }

        
        cout << x << endl; 
        queries++;

        
        int resp;
        if (!read_int(resp)) {
            finish(_pe, format("Failed to read response for guess %d", x));
        }

        if (resp == -1) {
            
            misses++;
            
            
            if (history[x] != -2 && history[x] != -1) {
                 finish(_wa, format("Inconsistency: value %d now claimed miss, previously claimed at index %d", x, history[x]));
            }
            history[x] = -1;
        } else {
            
            if (resp < 1 || resp > k) {
                finish(_wa, format("Response index %d out of bounds [1, %d]", resp, k));
            }
            
            
            if (history[x] != -2 && history[x] != resp) {
                if (history[x] == -1)
                    finish(_wa, format("Inconsistency: value %d claimed at %d, but previously missed", x, resp));
                else
                    finish(_wa, format("Inconsistency: value %d claimed at %d, but previously at %d", x, resp, history[x]));
            }
            
            
            if (history[x] == -2) {
                if (index_revealed[resp]) {
                    finish(_wa, format("Index %d claimed for value %d, but already used by another value", resp, x));
                }
                history[x] = resp;
                index_revealed[resp] = true;
                revealed_count++;
            }
        }
    }

    
    cout << -1 << endl;
    queries++;

    
    vector<int> seq;
    seq.reserve(k);
    for (int i = 0; i < k; i++) {
        int val;
        if (!read_int(val)) {
             finish(_pe, format("Failed to read sequence element %d of %d", i+1, k));
        }
        seq.push_back(val);
    }

    
    if (seq.empty()) finish(_wa, "Sequence is empty");
    
    if (seq[0] != 0) {
        finish(_wa, format("Sequence must start with 0, found %d", seq[0]));
    }
    if (seq.back() != 100000) {
        finish(_wa, format("Sequence must end with 100000, found %d", seq.back()));
    }

    
    vector<bool> in_seq(100001, false);
    in_seq[seq[0]] = true;

    for (int i = 1; i < k; i++) {
        int diff = seq[i] - seq[i-1];
        if (diff != 1 && diff != 2) {
            finish(_wa, format("Invalid step at index %d: %d -> %d (diff %d). Must be 1 or 2.", i+1, seq[i-1], seq[i], diff));
        }
        if (seq[i] < 0 || seq[i] > 100000) {
            finish(_wa, format("Sequence value out of bounds: %d", seq[i]));
        }
        in_seq[seq[i]] = true;
    }

    
    for (int v = 0; v <= 100000; v++) {
        
        if (history[v] == -2) continue;

        if (history[v] == -1) {
            
            if (in_seq[v]) {
                finish(_wa, format("Contestant said %d was a miss, but it appears in the final sequence", v));
            }
        } else {
            
            int idx = history[v] - 1; 
            if (idx >= k) {
                finish(_wa, "Internal error: index out of bounds");
            }
            if (seq[idx] != v) {
                finish(_wa, format("Contestant said %d was at index %d, but sequence has %d at that position", v, history[v], seq[idx]));
            }
        }
    }

    finish(_ok, format("Correct. Misses forced: %d", misses));
    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 = 100001; 


static void log_metrics() {
    try {
        if (tout.is_open()) {
            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);

    
    
    
    
    
    int first_token = inf.readInt();
    vector<int> p;
    int max_val = 100000;
    
    if (first_token > 100) {
        
        
        int count = first_token;
        p.reserve(count);
        for(int i = 0; i < count; i++) {
            p.push_back(inf.readInt());
        }
    } else {
        
        int strategy = first_token;
        long long seed = inf.readLong();
        
        p.resize(max_val + 1);
        iota(p.begin(), p.end(), 0);
        
        mt19937_64 rng(seed);
        
        if (strategy == 0) { 
            
            shuffle(p.begin(), p.end(), rng);
        } else if (strategy == 1) { 
            
            
        } else if (strategy == 2) { 
            
            reverse(p.begin(), p.end());
        } else if (strategy == 3) { 
            
            vector<int> tmp;
            tmp.reserve(p.size());
            int l = 0, r = p.size() - 1;
            while(l <= r) {
                if (l == r) tmp.push_back(p[l++]);
                else {
                    tmp.push_back(p[l++]);
                    tmp.push_back(p[r--]);
                }
            }
            p = tmp;
        } else if (strategy == 4) { 
            
            sort(p.begin(), p.end(), [](int a, int b){
                return abs(a - 50000) < abs(b - 50000);
            });
        } else { 
            
            shuffle(p.begin(), p.end(), rng);
        }
    }

    
    query_limit = p.size();
    log_metrics();

    
    int k;
    if (!(cin >> k)) {
        finish(_wa, "Failed to read k from contestant");
    }
    
    
    
    if (k < 50001 || k > 100001) {
        finish(_wa, "Invalid k: " + to_string(k) + " (must be between 50001 and 100001)");
    }

    
    
    int misses = 0;
    int found_cnt = 0;
    int p_idx = 0;
    
    
    vector<int> known_seq(k + 1, -2); 
    
    vector<bool> is_miss(max_val + 1, false);

    while (misses < 33333) {
        
        if (found_cnt == k) {
            finish(_wa, "Contestant revealed all numbers before forcing 33333 misses");
        }
        
        if (p_idx >= (int)p.size()) {
            
            finish(_wa, "Exhausted all guesses without finding sequence (inconsistent state)");
        }

        int guess = p[p_idx++];
        
        
        cout << guess << endl;
        queries++;
        if (queries % 1000 == 0) log_metrics(); 
        
        
        if (queries > 200000) {
            finish(_pe, "Too many queries");
        }
        
        
        int resp;
        if (!(cin >> resp)) {
            finish(_wa, "Unexpected EOF reading query response");
        }
        
        if (resp == -1) {
            misses++;
            is_miss[guess] = true;
        } else {
            
            if (resp < 1 || resp > k) {
                finish(_wa, "Response index out of range: " + to_string(resp));
            }
            
            if (known_seq[resp] != -2) {
                
                if (known_seq[resp] != guess) {
                    finish(_wa, "Inconsistent response: index " + to_string(resp) + " reported for " + to_string(guess) + " but previously " + to_string(known_seq[resp]));
                }
            } else {
                known_seq[resp] = guess;
                found_cnt++;
            }
        }
    }
    
    
    
    cout << -1 << endl;
    
    
    
    vector<int> final_seq;
    final_seq.reserve(k);
    for(int i = 0; i < k; i++) {
        int val;
        if (!(cin >> val)) {
            finish(_wa, "Failed to read final sequence");
        }
        final_seq.push_back(val);
    }
    
    
    if (final_seq[0] != 0) {
        finish(_wa, "Sequence must start with 0");
    }
    if (final_seq.back() != 100000) {
        finish(_wa, "Sequence must end with 100000");
    }
    if ((int)final_seq.size() != k) {
        finish(_wa, "Sequence length mismatch");
    }
    
    
    for(size_t i = 1; i < final_seq.size(); i++) {
        long long diff = (long long)final_seq[i] - final_seq[i-1];
        if (diff != 1 && diff != 2) {
            finish(_wa, "Invalid step size " + to_string(diff) + " at index " + to_string(i+1));
        }
    }
    
    
    for(int i = 1; i <= k; i++) {
        
        if (known_seq[i] != -2) {
            if (final_seq[i-1] != known_seq[i]) {
                finish(_wa, "Final sequence mismatch at index " + to_string(i) + ": expected " + to_string(known_seq[i]) + ", got " + to_string(final_seq[i-1]));
            }
        }
    }
    
    
    for(int x : final_seq) {
        if (x >= 0 && x <= max_val) {
            if (is_miss[x]) {
                finish(_wa, "Value " + to_string(x) + " is in final sequence but was reported as MISS");
            }
        }
    }
    
    finish(_ok, "Correct");
    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 min_val = 0;
    int max_val = 100000;
    int count = max_val - min_val + 1; 

    if (mode == "non") {
        
        
        
        vector<int> p(count);
        iota(p.begin(), p.end(), min_val);

        long long seed_val = 0;
        
        if (argc > 1) seed_val = atoll(argv[1]);

        if (seed_val == 1) {
            
            
        } else if (seed_val == 2) {
            
            reverse(p.begin(), p.end());
        } else if (seed_val == 3) {
            
            vector<int> temp;
            temp.reserve(count);
            int l = 0, r = count - 1;
            while (l <= r) {
                if (l == r) {
                    temp.push_back(p[l]);
                    l++;
                } else {
                    temp.push_back(p[l++]);
                    temp.push_back(p[r--]);
                }
            }
            p = temp;
        } else {
            
            shuffle(p.begin(), p.end());
        }

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

    } else if (mode == "adp") {
        
        
        
        long long seed_val = 0;
        if (argc > 1) seed_val = atoll(argv[1]);
        
        int strategy = 0;
        
        
        
        
        
        
        
        if (seed_val == 1) strategy = 1;
        else if (seed_val == 2) strategy = 2;
        else if (seed_val == 3) strategy = 3;
        else {
            
            strategy = rnd.next(0, 5);
        }

        int sub_seed = rnd.next(1, 1000000000);
        
        cout << strategy << " " << sub_seed << endl;

    } else {
        quitf(_fail, "Unknown mode: %s", mode.c_str());
    }

    return 0;
}