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

There are $n$ flowers arranged in a line from left to right, which are numbered from 1 to $n$ in that order. Each flower is either a lily or a rose. For an integer $j$ between 0 and $n$ , inclusive, let $l _ { j }$ denote the number of lilies among the leftmost $j$ flowers, and let $r _ { j }$ denote the number of roses among the rightmost $n - j$ flowers.

Initially, only the number of flowers $n$ is provided to you. The types of the flowers are hidden. You can obtain information on the flowers by making queries. In one query, you can perform one of the following.

Type query: Specify an integer $i$ between 1 and $n$ , inclusive. You will then receive the type of flower $i$

Multiply query: Specify an integer $j$ between 0 and $n$ , inclusive. You will then receive the value of $l _ { j } \times r _ { j }$

Your task is to find an integer $k$ between 0 and $n$ , inclusive, for which $l _ { k } = r _ { k }$ by making a limited number of queries. You can assume that at least one such integer exists for the arrangement of the flower types. Note that you do not need to identify the type of each flower.

# Interaction

The first line of input contains one integer $t$ $1 \leq t \leq 1 0 0 $ ) representing the number of test cases. After that, $t$ test cases follow. Each of them is presented as follows.

The first line of input for each test case contains an integer $n$ $1 \leq n \leq 1 0 0$ ). After reading it, your program can start making queries. For each query, your program should write a line containing one of the following:

• “type i” to perform a Type query by specifying an integer $i$ $( 1 \leq i \leq n )$ ). In response, an input line containing a string either lily or rose becomes available, indicating the type of flower $i$ .   
• “multi $j ^ {  }$ to perform a Multiply query by specifying an integer $j$ $0 \leq j \leq n \}$ . In response, an input line containing the integer $l _ { j } \times r _ { j }$ becomes available.

Your program is allowed to make up to 10 queries for each test case. This means the total number of Type queries and Multiply queries combined must not exceed 10. If your program makes more than 10 queries, it will be judged as “Wrong Answer”.

When your program identifies an integer $k$ such that $l _ { k } = r _ { k }$ , it should write a line of the form “answer k” $0 \leq$ $k \leq n$ ). Note that providing the answer does not count as a query.

The input guarantees that at least one correct output exists. If there are multiple correct outputs, any one of them will be accepted.

After writing the answer line, your program should start processing the next test case. When all $t$ test cases have been processed, the interaction stops and your program should terminate.

Notes on interactive judging:

• The evaluation is non-adversarial, meaning that the types of the flowers are chosen in advance rather than in response to your queries.

The 2025 ICPC Asia Pacific Championship Problem H: Secret Lilies and Roses

# The 2025 ICPC AsiaPacific Championship

Hosted by the National University of Singapore

• Do not forget to flush output buffers after writing. See the “Judging Details” document for details. • You are provided with a command-line tool for local testing, together with input files corresponding to the sample interactions. You can download these files from DOMjudge. The tool has comments at the top to explain its use.

![](images/2ad6a5a3d503e25a8bdb68e59daee94988aa95d432b10793f3b574ec95355091.jpg)

# Explanation for the sample interaction #1

For the first test case, nine flowers are arranged as shown in the following figure. In response to the third query, $l _ { 6 } \times r _ { 6 } = 3 \times 2 = 6$ is returned, and in response to the fourth query, $l _ { 3 } \times r _ { 3 } = 1 \times 3 = 3$ is returned. Since $l _ { 5 } = r _ { 5 } = 3$ , $k = 5$ is a correct output.

![](images/597ad3524e4f9230625a671a47f0e8e5a2169fcda791360c64ae40bf64075d05.jpg)

For the second test case, all three flowers are assumed to be roses.

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


const int HARD_CAP = 20000;

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

    
    int T = inf.readInt();
    
    
    
    query_limit = (long long)T * 10;
    log_metrics();

    
    cout << T << endl;

    for (int t = 1; t <= T; ++t) {
        
        int N = inf.readInt();
        string S = inf.readToken(); 

        if ((int)S.size() != N) {
            finish(_fail, format("Case %d: Hidden string length %d does not match N=%d", t, (int)S.size(), N));
        }

        
        cout << N << endl;

        int queries_this_case = 0;
        bool case_active = true;

        while (case_active) {
            
            if (queries > HARD_CAP) {
                finish(_pe, "Hard query limit exceeded (possible infinite loop)");
            }

            string cmd;
            if (!(cin >> cmd)) {
                finish(_pe, "Unexpected EOF reading command");
            }

            
            string lower_cmd = cmd;
            for (char &c : lower_cmd) c = tolower(c);

            if (lower_cmd == "answer" || lower_cmd == "!") {
                int k;
                if (!(cin >> k)) {
                    finish(_pe, "Expected integer k after answer");
                }

                if (k < 0 || k > N) {
                    finish(_wa, format("Case %d: Answer k=%d out of range [0, %d]", t, k, N));
                }

                
                
                int l_k = 0;
                for (int i = 0; i < k; ++i) {
                    if (S[i] == 'L') l_k++;
                }

                
                int r_k = 0;
                for (int i = k; i < N; ++i) {
                    if (S[i] == 'R') r_k++;
                }

                if (l_k != r_k) {
                    finish(_wa, format("Case %d: Incorrect answer k=%d (l_k=%d, r_k=%d)", t, k, l_k, r_k));
                }

                
                case_active = false;

            } else if (lower_cmd == "type") {
                queries++;
                queries_this_case++;
                log_metrics();

                if (queries_this_case > 10) {
                    finish(_wa, format("Case %d: Query limit exceeded (>10)", t));
                }

                int i;
                if (!(cin >> i)) {
                    finish(_pe, "Expected index i for type query");
                }

                if (i < 1 || i > N) {
                    finish(_wa, format("Type query index %d out of range [1, %d]", i, N));
                }

                
                char type = S[i-1];
                if (type == 'L') cout << "lily" << endl;
                else cout << "rose" << endl;

            } else if (lower_cmd == "multi") {
                queries++;
                queries_this_case++;
                log_metrics();

                if (queries_this_case > 10) {
                    finish(_wa, format("Case %d: Query limit exceeded (>10)", t));
                }

                int j;
                if (!(cin >> j)) {
                    finish(_pe, "Expected index j for multi query");
                }

                if (j < 0 || j > N) {
                    finish(_wa, format("Multi query index %d out of range [0, %d]", j, N));
                }

                
                int l_j = 0;
                for (int x = 0; x < j; ++x) {
                    if (S[x] == 'L') l_j++;
                }

                int r_j = 0;
                for (int x = j; x < N; ++x) {
                    if (S[x] == 'R') r_j++;
                }

                cout << (long long)l_j * r_j << endl;

            } else {
                finish(_pe, format("Unknown command: %s", cmd.c_str()));
            }
        }
    }

    finish(_ok, "All test cases passed");
    return 0;
}


Adaptive interactor (C++):

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

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

    
    if (t == -1) {
        if (seed_val == 1) t = 10;      
        else if (seed_val == 2) t = 5;  
        else t = 10;                    
    }

    cout << t << endl;

    for (int i = 0; i < t; ++i) {
        int n;
        if (fixed_n != -1) {
            n = fixed_n;
        } else {
            if (seed_val == 1) {
                
                n = rnd.next(1, 5);
            } else if (seed_val == 2) {
                
                n = 100;
            } else if (seed_val == 3) {
                
                n = rnd.next(90, 100);
            } else {
                
                n = rnd.next(1, 100);
            }
        }

        string s = "";
        
        
        if (seed_val == 1) {
            
            for (int j = 0; j < n; ++j) s += (rnd.next(2) ? 'L' : 'R');
        } else {
            int strategy = rnd.next(100);
            if (strategy < 10) {
                
                s = string(n, 'L');
            } else if (strategy < 20) {
                
                s = string(n, 'R');
            } else if (strategy < 30) {
                
                for (int j = 0; j < n; ++j) s += (j % 2 == 0 ? 'L' : 'R');
            } else if (strategy < 40) {
                
                for (int j = 0; j < n; ++j) s += (j % 2 == 0 ? 'R' : 'L');
            } else if (strategy < 55) {
                
                int k = rnd.next(0, n);
                for (int j = 0; j < n; ++j) s += (j < k ? 'L' : 'R');
            } else if (strategy < 70) {
                
                int k = rnd.next(0, n);
                for (int j = 0; j < n; ++j) s += (j < k ? 'R' : 'L');
            } else {
                
                for (int j = 0; j < n; ++j) s += (rnd.next(2) ? 'L' : 'R');
            }
        }

        
        if (mode == "non") {
            
            cout << n << endl;
            cout << s << endl;
        } else {
            
            
            int k = 0;
            for (char c : s) if (c == 'R') k++;
            cout << n << " " << k << endl;
        }
    }

    return 0;
}