Problem: cf1776_i
Difficulty: medium
Categories: game, greedy, math
Time limit: 2000 ms, memory limit: 256 MB

The two siblings Alberto and Beatrice have to eat a spinach pizza together. However, none of them likes spinach, so they both want to eat as little as possible.

The pizza has the shape of a strictly convex polygon with $n$ vertices located at integer coordinates $(x_1, y_1), \, (x_2, y_2), \, \dots, \, (x_n, y_n)$ of the plane.

The siblings have decided to eat the pizza in the following way: taking turns, starting with Alberto, each sibling chooses a vertex of the remaining part of the pizza and eats out the triangle determined by its two neighboring edges. In this way, after each of the first $n - 3$ turns the pizza will have one less vertex. The game ends after the $(n - 2)$-th turn, when all the pizza has been eaten.

Assuming that Alberto and Beatrice choose the slices to eat optimally, which of the siblings manages to eat at most half of the pizza? You should identify a sibling that has a strategy to do so and help them choose the slices appropriately. Note that it is possible that both Alberto and Beatrice end up eating exactly half of the area if they choose their slices optimally.

Input

The first line contains a single integer $n$ ($4 \le n \le 100$) — the number of vertices.

The next $n$ lines contain two integers $x_i$ and $y_i$ each ($-10^6 \le x_i, y_i \le 10^6$) — the coordinates of the $i$-th vertex of the polygon representing the initial shape of the pizza.

It is guaranteed that the polygon is strictly convex and that its vertices are given in counterclockwise order.

Interaction

First, you should print a line containing either the string $\texttt{Alberto}$ or the string $\texttt{Beatrice}$ — the sibling that you will help to win.

Then, for the next $n - 2$ turns, you will alternate with the judge in choosing a slice of the pizza and removing it, starting with you if you chose to help Alberto, or starting with the judge if you chose to help Beatrice.

* When it is your turn, print a single line containing an integer $p$ ($1 \leq p \leq n$) that has not been chosen before, indicating that you want to eat the slice determined by the vertex located at $(x_p, y_p)$.
* When it is the judge's turn, read an integer $q$ ($1 \leq q \leq n$), indicating that the other player eats the slice determined by the vertex located at $(x_q, y_q)$. It is guaranteed that $q$ has not been chosen before.

If one of your interactions is malformed, the interactor terminates immediately and your program receives the verdict $\texttt{WRONG-ANSWER}$. Otherwise, you will receive $\texttt{CORRECT}$ if at the end your player has eaten at most half of the pizza, and $\texttt{WRONG-ANSWER}$ otherwise.

After printing a line do not forget to end the line and flush the output. Otherwise, you will get the verdict $\texttt{TIMELIMIT}$. To flush the output, use:

* $\texttt{fflush(stdout)}$ in C;
* $\texttt{fflush(stdout)}$, $\texttt{cout <}\texttt{< flush}$ or $\texttt{cout.flush()}$ in C++;
* $\texttt{System.out.flush()}$ in Java and Kotlin;
* $\texttt{sys.stdout.flush()}$ in Python.

Examples

Input

```
4
0 0
6 1
5 3
1 4
```

Output

```
-
```

Input

```
6
0 0
2 0
3 2
2 4
0 4
-1 2
```

Output

```
-
```

Input

```
7
0 0
2 0
5 2
4 5
1 5
-1 4
-1 2
```

Output

```
-
```

Note

In the first sample, the pizza has area $15$. Alberto can eat less than half of the pizza by eating the slice around vertex $2$ (which has area $6.5$) or around vertex $3$ (which has area $3.5$).

 ![](https://espresso.codeforces.com/5c793cf174b810e32885c20e67a653a8522f4e88.png) 

In the second sample, it can be proved that both players will eat exactly half of the pizza if they eat optimally. Therefore it is possible to choose to help either Alberto or Beatrice.

In the third sample, it is possible to show that only Beatrice has a strategy to eat at most half of the pizza. The following is an example of a valid interaction (after reading the input):

 \begin{array}{|c|c|c|} \hline \textbf{Contestant} & \textbf{Judge} & \textbf{Explanation} \\ \hline \texttt{Beatrice} & & \text{The contestant will help Beatrice} \\ \hline & \texttt{7} & \text{Alberto eats the triangle with vertices $6$, $7$, $1$ and area $1$} \\ \hline \texttt{2} & & \text{Beatrice eats the triangle with vertices $1$, $2$, $3$ and area $2$} \\ \hline & \texttt{5} & \text{Alberto eats the triangle with vertices $4$, $5$, $6$ and area $1.5$} \\ \hline \texttt{4} & & \text{Beatrice eats the triangle with vertices $3$, $4$, $6$ and area $8$} \\ \hline & \texttt{6} & \text{Alberto eats the triangle with vertices $3$, $6$, $1$ and area $11$} \\ \hline \end{array}  The total area eaten by Alberto is $13.5$ and the total area eaten by Beatrice is $10$, which is less than half the area of the whole pizza. The actions performed by the contestant and the judge in this example of interaction may be non-optimal. The process is illustrated below: ![](https://espresso.codeforces.com/46ad7ab3420cde43230c826a0a54a5d8c78de0f9.png)

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 {
        if (query_limit != 0) {
            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());
}


template<typename... Args>
static void finish(TResult verdict, const char* fmt, Args... args) {
    log_metrics();
    quitf(verdict, fmt, args...);
}

struct Point {
    long long x, y;
};



long long cross_product(Point a, Point b, Point c) {
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}

int n;
vector<Point> poly;
vector<int> L, R;
vector<bool> used;

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

    
    n = inf.readInt();
    query_limit = n - 2; 
    
    poly.resize(n);
    for (int i = 0; i < n; i++) {
        poly[i].x = inf.readInt();
        poly[i].y = inf.readInt();
    }

    
    cout << n << endl;
    for (int i = 0; i < n; i++) {
        cout << poly[i].x << " " << poly[i].y << endl;
    }
    cout.flush(); 

    
    L.resize(n);
    R.resize(n);
    used.assign(n, false);
    for (int i = 0; i < n; i++) {
        L[i] = (i - 1 + n) % n;
        R[i] = (i + 1) % n;
    }

    
    long long total_area_2x = 0;
    for (int i = 0; i < n; i++) {
        total_area_2x += cross_product({0,0}, poly[i], poly[(i+1)%n]);
    }
    total_area_2x = std::abs(total_area_2x);

    log_metrics(); 

    
    string choice;
    if (!(cin >> choice)) finish(_wa, "No choice provided (expected Alberto/Beatrice)");
    
    bool user_is_alberto;
    if (choice == "Alberto") user_is_alberto = true;
    else if (choice == "Beatrice") user_is_alberto = false;
    else finish(_wa, "Invalid choice '%s', expected 'Alberto' or 'Beatrice'", choice.c_str());

    long long user_area_2x = 0;

    
    for (int turn = 1; turn <= n - 2; turn++) {
        queries = turn; 
        
        
        bool judge_turn = false;
        if (user_is_alberto) {
            
            if (turn % 2 == 0) judge_turn = true;
        } else {
            
            if (turn % 2 != 0) judge_turn = true;
        }

        int p_idx = -1; 

        if (judge_turn) {
            
            
            long long best_val = -1;
            int best_idx = -1;

            
            for (int i = 0; i < n; i++) {
                if (!used[i]) {
                    
                    long long current_area = std::abs(cross_product(poly[L[i]], poly[i], poly[R[i]]));
                    if (best_idx == -1 || current_area < best_val) {
                        best_val = current_area;
                        best_idx = i;
                    }
                }
            }
            p_idx = best_idx;
            
            cout << (p_idx + 1) << endl; 
        } else {
            
            string token;
            if (!(cin >> token)) finish(_wa, "Unexpected end of input waiting for move");
            
            
            if (token == "?") {
                if (!(cin >> token)) finish(_wa, "Unexpected end of input after '?'");
            }
            if (!token.empty() && token[0] == '!') finish(_wa, "Unexpected '!' token during game");

            int p_user = 0;
            try {
                size_t pos;
                p_user = stoi(token, &pos);
                if (pos != token.size()) finish(_wa, "Trailing garbage in integer token '%s'", token.c_str());
            } catch (...) {
                finish(_wa, "Invalid integer format '%s'", token.c_str());
            }

            if (p_user < 1 || p_user > n) finish(_wa, "Index %d out of bounds [1, %d]", p_user, n);
            p_idx = p_user - 1;

            if (used[p_idx]) finish(_wa, "Vertex %d already removed", p_user);

            
            long long area = std::abs(cross_product(poly[L[p_idx]], poly[p_idx], poly[R[p_idx]]));
            user_area_2x += area;
        }

        
        int left = L[p_idx];
        int right = R[p_idx];
        R[left] = right;
        L[right] = left;
        used[p_idx] = true;

        
        if (turn % 10 == 0) log_metrics();
    }
    
    log_metrics();

    
    
    
    
    if (2 * user_area_2x <= total_area_2x) {
        finish(_ok, "Correct: ate <= half (User=%.1f, Total=%.1f)", user_area_2x / 2.0, total_area_2x / 2.0);
    } else {
        finish(_wa, "Wrong Answer: ate > half (User=%.1f, Total=%.1f)", user_area_2x / 2.0, total_area_2x / 2.0);
    }

    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 = 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 Point {
    long long x, y;
    int id; 
};


long long cross_product(Point a, Point b, Point c) {
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}


long long get_area2(const vector<Point>& poly, int i) {
    int n = poly.size();
    Point prev = poly[(i - 1 + n) % n];
    Point curr = poly[i];
    Point next = poly[(i + 1) % n];
    return abs(cross_product(prev, curr, next));
}

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

    
    int n = inf.readInt();
    query_limit = n - 2;
    
    log_metrics();

    vector<Point> initial_poly(n);
    for (int i = 0; i < n; i++) {
        initial_poly[i].x = inf.readInt();
        initial_poly[i].y = inf.readInt();
        initial_poly[i].id = i + 1;
    }

    
    long long total_area2 = 0;
    for (int i = 0; i < n; i++) {
        total_area2 += cross_product({0,0,0}, initial_poly[i], initial_poly[(i + 1) % n]);
    }
    total_area2 = abs(total_area2);

    
    
    cout << n << endl;
    for (int i = 0; i < n; i++) {
        cout << initial_poly[i].x << " " << initial_poly[i].y << endl;
    }
    cout.flush();

    
    string choice = ouf.readToken("Alberto|Beatrice");
    bool contestant_is_alberto = (choice == "Alberto");

    
    vector<Point> current_poly = initial_poly;
    set<int> removed_ids;
    long long contestant_area2 = 0;
    long long judge_area2 = 0;

    
    for (int turn = 1; turn <= n - 2; turn++) {
        queries++;
        
        bool is_alberto_turn = (turn % 2 != 0);
        bool is_contestant_turn = (is_alberto_turn == contestant_is_alberto);

        if (is_contestant_turn) {
            
            int p_id = ouf.readInt(1, n);
            
            
            if (removed_ids.count(p_id)) {
                finish(_wa, format("Vertex %d has already been removed.", p_id));
            }
            
            int idx = -1;
            for (int i = 0; i < (int)current_poly.size(); i++) {
                if (current_poly[i].id == p_id) {
                    idx = i;
                    break;
                }
            }
            
            if (idx == -1) {
                
                finish(_wa, format("Vertex %d is not in the current polygon.", p_id));
            }

            long long area = get_area2(current_poly, idx);
            contestant_area2 += area;
            
            removed_ids.insert(p_id);
            current_poly.erase(current_poly.begin() + idx);
        
        } else {
            
            
            
            
            long long best_metric = -5000000000000000000LL; 
            int best_idx = -1;
            int sz = current_poly.size();

            for (int i = 0; i < sz; i++) {
                long long my_area = get_area2(current_poly, i);
                long long opp_min_area = 0;

                
                if (sz - 1 > 2) {
                    
                    vector<Point> next_poly = current_poly;
                    next_poly.erase(next_poly.begin() + i);
                    
                    
                    long long min_a = 5000000000000000000LL; 
                    for (int j = 0; j < (int)next_poly.size(); j++) {
                        long long a = get_area2(next_poly, j);
                        if (a < min_a) min_a = a;
                    }
                    opp_min_area = min_a;
                }

                
                
                long long metric = opp_min_area - my_area;
                
                if (metric > best_metric) {
                    best_metric = metric;
                    best_idx = i;
                } else if (metric == best_metric) {
                    
                    if (my_area < get_area2(current_poly, best_idx)) {
                        best_idx = i;
                    }
                }
            }
            
            int p_id = current_poly[best_idx].id;
            long long area = get_area2(current_poly, best_idx);
            judge_area2 += area;
            
            removed_ids.insert(p_id);
            current_poly.erase(current_poly.begin() + best_idx);
            
            cout << p_id << endl;
            cout.flush();
        }
        
        
        if (turn % 10 == 0) log_metrics();
    }

    
    
    if (contestant_area2 * 2 <= total_area2) {
        finish(_ok, format("Contestant area %lld <= %lld (Total/2).", contestant_area2, total_area2 / 2));
    } else {
        finish(_wa, format("Contestant area %lld > %lld (Total/2).", contestant_area2, total_area2 / 2));
    }

    return 0;
}


Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

struct Point {
    long long x, y;
};


int quad(Point p) {
    if (p.x > 0 && p.y >= 0) return 1;
    if (p.x <= 0 && p.y > 0) return 2;
    if (p.x < 0 && p.y <= 0) return 3;
    if (p.x >= 0 && p.y < 0) return 4;
    return 0;
}


long long cross_product(Point a, Point b) {
    return a.x * b.y - a.y * b.x;
}


bool angle_cmp(Point a, Point b) {
    int qa = quad(a), qb = quad(b);
    if (qa != qb) return qa < qb;
    return cross_product(a, b) > 0;
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);
    
    
    
    int seed = atoi(argv[1]);
    string mode = opt<string>("mode", "non");

    
    if (seed == 1) {
        cout << "4\n0 0\n6 1\n5 3\n1 4\n";
        return 0;
    }
    if (seed == 2) {
        cout << "6\n0 0\n2 0\n3 2\n2 4\n0 4\n-1 2\n";
        return 0;
    }
    if (seed == 3) {
        cout << "7\n0 0\n2 0\n5 2\n4 5\n1 5\n-1 4\n-1 2\n";
        return 0;
    }

    
    int n;
    if (mode == "adp") {
        
        if (rnd.next(2) == 0) n = 100;
        else n = rnd.next(4, 100);
    } else {
        
        n = rnd.next(4, 100);
    }

    
    
    while (true) {
        
        int k = n + rnd.next(5, 20);
        int vec_range = 20000; 

        vector<long long> vx(k), vy(k);
        long long sum_x = 0, sum_y = 0;

        
        for (int i = 0; i < k; i++) {
            vx[i] = rnd.next(1, vec_range);
            if (rnd.next(2)) vx[i] = -vx[i];
            sum_x += vx[i];

            vy[i] = rnd.next(1, vec_range);
            if (rnd.next(2)) vy[i] = -vy[i];
            sum_y += vy[i];
        }

        
        while (sum_x != 0) {
            int i = rnd.next(k);
            if (sum_x > 0) { vx[i]--; sum_x--; }
            else { vx[i]++; sum_x++; }
        }
        while (sum_y != 0) {
            int i = rnd.next(k);
            if (sum_y > 0) { vy[i]--; sum_y--; }
            else { vy[i]++; sum_y++; }
        }

        
        vector<Point> vecs;
        for (int i = 0; i < k; i++) {
            if (vx[i] == 0 && vy[i] == 0) continue;
            vecs.push_back({vx[i], vy[i]});
        }

        if ((int)vecs.size() < n) continue;

        
        sort(vecs.begin(), vecs.end(), angle_cmp);

        
        vector<Point> merged;
        merged.push_back(vecs[0]);
        for (size_t i = 1; i < vecs.size(); i++) {
            Point& last = merged.back();
            Point curr = vecs[i];
            if (quad(last) == quad(curr) && cross_product(last, curr) == 0) {
                last.x += curr.x;
                last.y += curr.y;
            } else {
                merged.push_back(curr);
            }
        }
        
        if (merged.size() > 1) {
            Point& first = merged.front();
            Point& last = merged.back();
            if (quad(first) == quad(last) && cross_product(last, first) == 0) {
                first.x += last.x;
                first.y += last.y;
                merged.pop_back();
            }
        }

        if ((int)merged.size() < n) continue;

        
        
        while ((int)merged.size() > n) {
            int idx = rnd.next((int)merged.size());
            int next_idx = (idx + 1) % merged.size();
            
            merged[idx].x += merged[next_idx].x;
            merged[idx].y += merged[next_idx].y;
            
            merged.erase(merged.begin() + next_idx);
        }

        
        bool ok = true;
        for (int i = 0; i < n; i++) {
            Point p1 = merged[i];
            Point p2 = merged[(i + 1) % n];
            
            
            if ((p1.x == 0 && p1.y == 0) || (p2.x == 0 && p2.y == 0)) { ok = false; break; }
            
            if (quad(p1) == quad(p2) && cross_product(p1, p2) == 0) { ok = false; break; }
        }
        if (!ok) continue;

        
        vector<Point> poly(n);
        Point curr = {0, 0};
        long long min_x = 0, max_x = 0, min_y = 0, max_y = 0;

        for (int i = 0; i < n; i++) {
            poly[i] = curr;
            min_x = min(min_x, curr.x);
            max_x = max(max_x, curr.x);
            min_y = min(min_y, curr.y);
            max_y = max(max_y, curr.y);
            curr.x += merged[i].x;
            curr.y += merged[i].y;
        }

        
        long long shift_x = -(min_x + max_x) / 2;
        long long shift_y = -(min_y + max_y) / 2;
        bool coords_ok = true;

        for (int i = 0; i < n; i++) {
            poly[i].x += shift_x;
            poly[i].y += shift_y;
            if (abs(poly[i].x) > 1000000 || abs(poly[i].y) > 1000000) coords_ok = false;
        }

        if (!coords_ok) continue;

        
        cout << n << "\n";
        for (int i = 0; i < n; i++) {
            cout << poly[i].x << " " << poly[i].y << "\n";
        }
        break;
    }

    return 0;
}