Problem: cf1056_c
Difficulty: easy
Categories: greedy, data structures, game
Time limit: 1000 ms, memory limit: 256 MB

Don't you tell me what you think that I can be

If you say that Arkady is a bit old-fashioned playing checkers, you won't be right. There is also a modern computer game Arkady and his friends are keen on. We won't discuss its rules, the only feature important to this problem is that each player has to pick a distinct hero in the beginning of the game.

There are $2$ teams each having $n$ players and $2n$ heroes to distribute between the teams. The teams take turns picking heroes: at first, the first team chooses a hero in its team, after that the second team chooses a hero and so on. Note that after a hero is chosen it becomes unavailable to both teams.

The friends estimate the power of the $i$-th of the heroes as $p_i$. Each team wants to maximize the total power of its heroes. However, there is one exception: there are $m$ pairs of heroes that are especially strong against each other, so when any team chooses a hero from such a pair, the other team must choose the other one on its turn. Each hero is in at most one such pair.

This is an interactive problem. You are to write a program that will optimally choose the heroes for one team, while the jury's program will play for the other team. Note that the jury's program may behave inefficiently, in this case you have to take the opportunity and still maximize the total power of your team. Formally, if you ever have chance to reach the total power of $q$ or greater regardless of jury's program choices, you must get $q$ or greater to pass a test.

Input

The first line contains two integers $n$ and $m$ ($1 \le n \le 10^3$, $0 \le m \le n$) — the number of players in one team and the number of special pairs of heroes.

The second line contains $2n$ integers $p_1, p_2, \ldots, p_{2n}$ ($1 \le p_i \le 10^3$) — the powers of the heroes.

Each of the next $m$ lines contains two integer $a$ and $b$ ($1 \le a, b \le 2n$, $a \ne b$) — a pair of heroes that are especially strong against each other. It is guaranteed that each hero appears at most once in this list.

The next line contains a single integer $t$ ($1 \le t \le 2$) — the team you are to play for. If $t = 1$, the first turn is yours, otherwise you have the second turn.

Interaction

When it is your turn, print a single integer $x$ ($1 \le x \le 2n$) — the index of the hero chosen by you. Note that you can't choose a hero previously chosen by either you of the other player, and you must follow the rules about special pairs of heroes.

When it is the other team's turn, read a line containing a single integer $x$ ($1 \le x \le 2n$) — the index of the hero chosen by the other team. It is guaranteed that this index is not chosen before and that the other team also follows the rules about special pairs of heroes.

After the last turn you should terminate without printing anything.

After printing your choice do not forget to output end of line and flush the output. Otherwise you will get Idleness limit exceeded. To do this, use:

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

Jury's answer $-1$ instead of a valid choice means that you made an invalid turn. Exit immediately after receiving $-1$ and you will see Wrong answer verdict. Otherwise you can get an arbitrary verdict because your solution will continue to read from a closed stream.

Examples

Input

```
3 1
1 2 3 4 5 6
2 6
1

2

4

1
```

Output

```
6

5

3
```

Input

```
3 1
1 2 3 4 5 6
1 5
2
6

1

3
```

Output

```
5

4

2
```

Note

In the first example the first turn is yours. In example, you choose $6$, the other team is forced to reply with $2$. You choose $5$, the other team chooses $4$. Finally, you choose $3$ and the other team choose $1$.

In the second example you have the second turn. The other team chooses $6$, you choose $5$, forcing the other team to choose $1$. Now you choose $4$, the other team chooses $3$ and you choose $2$.

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 << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
    }
}

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

static bool parseIntToken(const string& s, long long& out) {
    if (s.empty()) return false;
    int i = 0;
    bool neg = false;
    if (s[0] == '-') {
        neg = true;
        i = 1;
        if (i == (int)s.size()) return false;
    }
    long long val = 0;
    for (; i < (int)s.size(); ++i) {
        if (s[i] < '0' || s[i] > '9') return false;
        int d = s[i] - '0';
        if (val > (LLONG_MAX - d) / 10) return false;
        val = val * 10 + d;
    }
    out = neg ? -val : val;
    return true;
}

struct PairEntry {
    int powerHi;
    int hi;
    int lo;
    bool operator<(const PairEntry& other) const {
        if (powerHi != other.powerHi) return powerHi < other.powerHi;
        if (hi != other.hi) return hi < other.hi;
        return lo < other.lo;
    }
};

struct SingleEntry {
    int power;
    int idx;
    bool operator<(const SingleEntry& other) const {
        if (power != other.power) return power < other.power;
        return idx < other.idx;
    }
};

struct Heaps {
    priority_queue<PairEntry> pairs;
    priority_queue<SingleEntry> singles;
};

static Heaps buildHeaps(int n2,
                        const vector<int>& p,
                        const vector<int>& mate,
                        const vector<pair<int,int>>& pairList) {
    Heaps h;
    for (auto [a, b] : pairList) {
        int hi = (p[a] >= p[b]) ? a : b;
        int lo = (hi == a) ? b : a;
        h.pairs.push(PairEntry{p[hi], hi, lo});
    }
    for (int i = 1; i <= n2; ++i) {
        if (mate[i] == 0) h.singles.push(SingleEntry{p[i], i});
    }
    return h;
}

static int cleanPeekBestSingle(priority_queue<SingleEntry>& pq, const vector<char>& used) {
    while (!pq.empty() && used[pq.top().idx]) pq.pop();
    return pq.empty() ? 0 : pq.top().idx;
}

static int cleanPeekBestPairHi(priority_queue<PairEntry>& pq, const vector<char>& used) {
    while (!pq.empty() && (used[pq.top().hi] || used[pq.top().lo])) pq.pop();
    return pq.empty() ? 0 : pq.top().hi;
}

static int selectSingle(priority_queue<SingleEntry>& pq, const vector<char>& used) {
    while (!pq.empty() && used[pq.top().idx]) pq.pop();
    if (pq.empty()) return 0;
    int idx = pq.top().idx;
    pq.pop();
    return idx;
}

static PairEntry selectPair(priority_queue<PairEntry>& pq, const vector<char>& used) {
    while (!pq.empty() && (used[pq.top().hi] || used[pq.top().lo])) pq.pop();
    if (pq.empty()) return PairEntry{-1, -1, -1};
    PairEntry e = pq.top();
    pq.pop();
    return e;
}

static int selectFreeMoveGreedy(Heaps& h, const vector<int>& p, const vector<char>& used) {
    int bestSingle = cleanPeekBestSingle(h.singles, used);
    int bestPairHi = cleanPeekBestPairHi(h.pairs, used);

    int bestSinglePower = bestSingle ? p[bestSingle] : -1;
    int bestPairPower = bestPairHi ? p[bestPairHi] : -1;

    if (bestPairHi && (bestPairPower > bestSinglePower || !bestSingle)) {
        PairEntry e = selectPair(h.pairs, used);
        if (e.hi <= 0) return 0;
        return e.hi;
    } else {
        return selectSingle(h.singles, used);
    }
}

static long long simulateValue(int n,
                              int tContestant,
                              const vector<int>& p,
                              const vector<int>& mate,
                              const vector<pair<int,int>>& pairList) {
    int n2 = 2 * n;
    vector<char> used(n2 + 1, 0);
    Heaps h = buildHeaps(n2, p, mate, pairList);

    long long sum1 = 0, sum2 = 0;
    int forced[3] = {0, 0, 0};
    int curTeam = 1;

    for (int turn = 0; turn < 2 * n; ++turn) {
        int pick = 0;
        if (forced[curTeam]) {
            pick = forced[curTeam];
            forced[curTeam] = 0;
        } else {
            pick = selectFreeMoveGreedy(h, p, used);
        }
        if (pick <= 0 || pick > n2 || used[pick]) break;

        used[pick] = 1;
        if (curTeam == 1) sum1 += p[pick];
        else sum2 += p[pick];

        int partner = mate[pick];
        if (partner && !used[partner]) forced[3 - curTeam] = partner;

        curTeam = 3 - curTeam;
    }
    return (tContestant == 1) ? sum1 : sum2;
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n = inf.readInt(1, 1000, "n");
    int m = inf.readInt(0, n, "m");
    int n2 = 2 * n;

    vector<int> p(n2 + 1, 0);
    for (int i = 1; i <= n2; ++i) p[i] = inf.readInt(1, 1000, ("p[" + to_string(i) + "]").c_str());

    vector<int> mate(n2 + 1, 0);
    vector<pair<int,int>> pairs;
    pairs.reserve(m);
    vector<char> seen(n2 + 1, 0);
    for (int i = 0; i < m; ++i) {
        int a = inf.readInt(1, n2, "a");
        int b = inf.readInt(1, n2, "b");
        if (a == b) finish(_pe, "invalid hidden input: a==b");
        if (seen[a] || seen[b]) finish(_pe, "invalid hidden input: hero appears in more than one pair");
        seen[a] = seen[b] = 1;
        mate[a] = b;
        mate[b] = a;
        pairs.push_back({a, b});
    }

    int t = inf.readInt(1, 2, "t");

    query_limit = n;
    log_metrics(); 

    const long long required_min = simulateValue(n, t, p, mate, pairs);

    
    cout << n << " " << m << "\n";
    for (int i = 1; i <= n2; ++i) {
        cout << p[i] << (i == n2 ? '\n' : ' ');
    }
    for (auto [a, b] : pairs) cout << a << " " << b << "\n";
    cout << t << "\n";
    cout.flush();

    
    vector<char> used(n2 + 1, 0);
    Heaps heaps = buildHeaps(n2, p, mate, pairs);

    int forcedForContestant = 0;
    int forcedForInteractor = 0;

    long long sumContestant = 0, sumInteractor = 0;

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    auto applyPick = [&](int who, int x) {
        used[x] = 1;
        if (who == t) sumContestant += p[x];
        else sumInteractor += p[x];
    };

    auto onPickSetsForced = [&](int who, int x) {
        int partner = mate[x];
        if (partner && !used[partner]) {
            if (who == t) {
                if (forcedForInteractor != 0) finish(_wa, "internal state: forcedForInteractor already set");
                forcedForInteractor = partner;
            } else {
                if (forcedForContestant != 0) finish(_wa, "internal state: forcedForContestant already set");
                forcedForContestant = partner;
            }
        }
    };

    int curTeam = 1;
    for (int turn = 0; turn < 2 * n; ++turn) {
        if (curTeam == t) {
            if (queries >= hard_cap) finish(_pe, "hard cap exceeded (too many contestant moves)");
            string tok;
            if (!(cin >> tok)) finish(_pe, "contestant output ended early");
            long long xll = 0;
            if (!parseIntToken(tok, xll)) finish(_pe, "non-integer contestant token");
            if (xll == -1) finish(_wa, "contestant output -1");
            if (xll < 1 || xll > n2) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "contestant chose out-of-range hero");
            }
            int x = (int)xll;

            ++queries;
            log_metrics();

            if (used[x]) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "contestant chose an already used hero");
            }
            if (forcedForContestant != 0 && x != forcedForContestant) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "contestant violated forced pair rule");
            }
            forcedForContestant = 0;

            applyPick(t, x);
            onPickSetsForced(t, x);
        } else {
            int x = 0;
            if (forcedForInteractor != 0) {
                x = forcedForInteractor;
                forcedForInteractor = 0;
                if (x < 1 || x > n2 || used[x]) finish(_wa, "interactor forced move invalid (internal error)");
            } else {
                x = selectFreeMoveGreedy(heaps, p, used);
                if (x == 0) finish(_wa, "interactor has no valid move (internal error)");
                if (used[x]) finish(_wa, "interactor selected used hero (internal error)");
            }

            cout << x << "\n";
            cout.flush();

            applyPick(3 - t, x);
            onPickSetsForced(3 - t, x);
        }

        curTeam = 3 - curTeam;
    }

    if (sumContestant + sumInteractor != accumulate(p.begin(), p.end(), 0LL)) {
        
        
    }

    if (sumContestant >= required_min) {
        finish(_ok, "ok");
    } else {
        finish(_wa, "suboptimal total power");
    }
}


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 << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

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

static bool readLongLongToken(long long& out) {
    string s;
    if (!(cin >> s)) return false;
    if (s.empty()) return false;
    int i = 0;
    bool neg = false;
    if (s[0] == '-') {
        neg = true;
        i = 1;
        if ((int)s.size() == 1) return false;
    }
    for (; i < (int)s.size(); ++i) {
        if (s[i] < '0' || s[i] > '9') return false;
    }
    try {
        out = stoll(s);
    } catch (...) {
        return false;
    }
    return true;
}

struct PairNode {
    int sum = 0;
    int hiVal = 0, loVal = 0;
    int hiIdx = 0, loIdx = 0;
    int id = -1;

    bool operator<(const PairNode& other) const {
        if (sum != other.sum) return sum < other.sum;
        if (hiVal != other.hiVal) return hiVal < other.hiVal;
        if (loVal != other.loVal) return loVal > other.loVal; 
        if (hiIdx != other.hiIdx) return hiIdx > other.hiIdx; 
        return id > other.id;
    }
};

struct SingleCmp {
    bool operator()(const pair<int,int>& a, const pair<int,int>& b) const {
        if (a.first != b.first) return a.first > b.first;   
        return a.second < b.second;                          
    }
};

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

    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n = 0, m = 0, t = 0;
    vector<int> p;
    vector<int> partner;
    vector<int> pairId;
    vector<pair<int,int>> pairs;
    vector<bool> alivePair;
    vector<bool> used;

    multiset<pair<int,int>, SingleCmp> singles;
    priority_queue<PairNode> pq;

    auto bad_input = [&](const string& msg) {
        finish(_pe, "bad hidden input: " + msg);
    };

    try {
        n = inf.readInt(1, 1000, "n");
        m = inf.readInt(0, n, "m");
        p.assign(2 * n + 1, 0);
        for (int i = 1; i <= 2 * n; ++i) p[i] = inf.readInt(1, 1000, "p_i");

        partner.assign(2 * n + 1, 0);
        pairId.assign(2 * n + 1, -1);
        pairs.reserve(m);

        for (int i = 0; i < m; ++i) {
            int a = inf.readInt(1, 2 * n, "a");
            int b = inf.readInt(1, 2 * n, "b");
            if (a == b) bad_input("pair endpoints equal");
            if (partner[a] != 0 || partner[b] != 0) bad_input("hero appears in multiple pairs");
            partner[a] = b;
            partner[b] = a;
            pairId[a] = i;
            pairId[b] = i;
            pairs.push_back({a, b});
        }

        t = inf.readInt(1, 2, "t");
    } catch (...) {
        bad_input("exception while reading");
    }

    
    cout << n << " " << m << "\n";
    for (int i = 1; i <= 2 * n; ++i) {
        cout << p[i] << (i == 2 * n ? '\n' : ' ');
    }
    for (auto [a, b] : pairs) {
        cout << a << " " << b << "\n";
    }
    cout << t << "\n";
    cout.flush();

    
    query_limit = n;
    const long long hard_cap = max(200000LL, 10LL * query_limit);
    log_metrics(); 

    used.assign(2 * n + 1, false);
    alivePair.assign(m, true);

    
    for (int i = 1; i <= 2 * n; ++i) {
        if (partner[i] == 0) singles.insert({p[i], i});
    }
    for (int i = 0; i < m; ++i) {
        int a = pairs[i].first;
        int b = pairs[i].second;
        int hiIdx = a, loIdx = b;
        int hiVal = p[a], loVal = p[b];
        if (hiVal < loVal || (hiVal == loVal && hiIdx > loIdx)) {
            swap(hiIdx, loIdx);
            swap(hiVal, loVal);
        }
        PairNode node;
        node.sum = hiVal + loVal;
        node.hiVal = hiVal;
        node.loVal = loVal;
        node.hiIdx = hiIdx;
        node.loIdx = loIdx;
        node.id = i;
        pq.push(node);
    }

    auto consume_pick = [&](int idx) {
        used[idx] = true;
        if (partner[idx] == 0) {
            auto it = singles.find({p[idx], idx});
            if (it != singles.end()) singles.erase(it);
        } else {
            int id = pairId[idx];
            if (id >= 0 && id < m && alivePair[id]) alivePair[id] = false;
        }
    };

    auto pick_free = [&]() -> int {
        while (!pq.empty()) {
            const auto& top = pq.top();
            if (top.id < 0 || top.id >= m) { pq.pop(); continue; }
            if (!alivePair[top.id]) { pq.pop(); continue; }
            if (used[top.hiIdx] || used[top.loIdx]) { pq.pop(); continue; }
            break;
        }

        bool hasPair = !pq.empty();
        bool hasSingle = !singles.empty();
        if (!hasPair && !hasSingle) return 0;

        if (hasPair) {
            const auto& top = pq.top();
            int bestSingle = hasSingle ? singles.begin()->first : -1;
            if (!hasSingle || top.sum > bestSingle) {
                return top.hiIdx;
            }
        }
        return singles.begin()->second;
    };

    int contestantTeam = t;     
    int judgeTeam = 3 - t;      
    long long score[3] = {0, 0, 0};
    int forcedFor[3] = {0, 0, 0}; 

    for (int turn = 1; turn <= 2 * n; ++turn) {
        int teamToMove = (turn % 2 == 1) ? 1 : 2;

        if (teamToMove == contestantTeam) {
            long long xll = 0;
            if (!readLongLongToken(xll)) finish(_pe, "unexpected EOF / non-integer from contestant");
            ++queries;
            if (queries > hard_cap) finish(_pe, "too many moves from contestant");

            if (xll == -1) finish(_wa, "contestant printed -1");
            if (xll < 1 || xll > 2LL * n) finish(_wa, "hero index out of range");

            int x = (int)xll;
            if (used[x]) finish(_wa, "hero already chosen");
            if (forcedFor[teamToMove] != 0 && x != forcedFor[teamToMove]) finish(_wa, "did not follow forced pair rule");

            forcedFor[teamToMove] = 0;
            consume_pick(x);
            score[teamToMove] += p[x];

            int y = partner[x];
            if (y != 0 && !used[y]) forcedFor[3 - teamToMove] = y;
            else forcedFor[3 - teamToMove] = 0;
        } else {
            int move = 0;
            if (forcedFor[teamToMove] != 0) {
                move = forcedFor[teamToMove];
                if (move < 1 || move > 2 * n || used[move]) finish(_pe, "internal forced move invalid");
            } else {
                move = pick_free();
                if (move == 0) finish(_pe, "internal: no legal move available");
                if (used[move]) finish(_pe, "internal: selected already used move");
            }

            cout << move << "\n";
            cout.flush();

            forcedFor[teamToMove] = 0;
            consume_pick(move);
            score[teamToMove] += p[move];

            int y = partner[move];
            if (y != 0 && !used[y]) forcedFor[3 - teamToMove] = y;
            else forcedFor[3 - teamToMove] = 0;
        }
    }

    finish(_ok, ("finished: contestant=" + to_string(score[contestantTeam]) + " judge=" + to_string(score[judgeTeam])).c_str());
}


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

static void rndShuffle(vector<int>& v) {
    for (int i = (int)v.size() - 1; i > 0; --i) {
        int j = rnd.next(0, i);
        swap(v[i], v[j]);
    }
}

struct GenCase {
    int n = 0, m = 0, t = 1;
    vector<int> p;                
    vector<pair<int,int>> pairs;  
};

static GenCase makeCorner1() {
    GenCase c;
    c.n = 1;
    c.m = 0;
    c.t = 1;
    c.p.assign(2 * c.n + 1, 0);
    c.p[1] = 1;
    c.p[2] = 1000;
    return c;
}

static GenCase makeCorner2() {
    GenCase c;
    c.n = 1;
    c.m = 1;
    c.t = 2;
    c.p.assign(2 * c.n + 1, 0);
    c.p[1] = 1000;
    c.p[2] = 1;
    c.pairs.push_back({1, 2});
    return c;
}

static GenCase makeCorner3() {
    GenCase c;
    c.n = 3;
    c.m = 2;
    c.t = 2;
    c.p.assign(2 * c.n + 1, 0);
    
    
    c.p[1] = 1000; c.p[2] = 1;    
    c.p[3] = 900;  c.p[4] = 800;  
    c.p[5] = 999;                 
    c.p[6] = 2;                   
    c.pairs.push_back({1, 2});
    c.pairs.push_back({3, 4});
    return c;
}

static GenCase makeRandomCase(long long seedVal, int nDefault, int mOpt, int maxP, int tOpt) {
    GenCase c;
    c.n = nDefault;
    int n = c.n;

    int m;
    if (mOpt >= 0) {
        m = min(mOpt, n);
    } else {
        
        int dec = rnd.next(0, max(1, n / 25));
        m = n - dec;
        if (rnd.next(0, 9) == 0) m = n;
    }
    c.m = m;

    if (tOpt == 1 || tOpt == 2) c.t = tOpt;
    else c.t = rnd.next(1, 2);

    c.p.assign(2 * n + 1, 0);

    vector<int> all(2 * n);
    for (int i = 0; i < 2 * n; ++i) all[i] = i + 1;
    rndShuffle(all);

    vector<int> pairedIdx;
    pairedIdx.reserve(2 * m);
    for (int i = 0; i < 2 * m; ++i) pairedIdx.push_back(all[i]);

    vector<int> singleIdx;
    for (int i = 2 * m; i < 2 * n; ++i) singleIdx.push_back(all[i]);

    
    
    int phase = (int)(seedVal % 11);
    for (int i = 0; i < m; ++i) {
        int a = pairedIdx[2 * i];
        int b = pairedIdx[2 * i + 1];

        int type = (i + phase) % 6;
        int x = 1, y = 1;

        if (type == 0) {
            x = maxP;
            y = rnd.next(1, max(1, maxP / 100));
        } else if (type == 1) {
            x = maxP - rnd.next(0, 3);
            y = maxP - rnd.next(8, 25);
        } else if (type == 2) {
            x = rnd.next(maxP * 2 / 3, maxP);
            y = rnd.next(1, maxP / 3);
        } else if (type == 3) {
            int base = rnd.next(maxP / 2, maxP * 3 / 4);
            x = base;
            y = base + rnd.next(-3, 3);
            y = max(1, min(maxP, y));
        } else if (type == 4) {
            x = rnd.next(maxP / 3, maxP * 2 / 3);
            y = rnd.next(maxP / 3, maxP * 2 / 3);
        } else {
            x = rnd.next(1, max(1, maxP / 4));
            y = rnd.next(1, max(1, maxP / 4));
        }

        if (rnd.next(0, 1) == 1) swap(x, y);

        c.p[a] = x;
        c.p[b] = y;
        c.pairs.push_back({a, b});
    }

    
    rndShuffle(singleIdx);
    int k = (int)singleIdx.size();
    int topBait = min(12, k);
    for (int i = 0; i < k; ++i) {
        int idx = singleIdx[i];
        if (i < topBait) {
            c.p[idx] = maxP - rnd.next(0, 2);
        } else if (i < min(k, 80)) {
            c.p[idx] = rnd.next(max(1, maxP / 2), maxP);
        } else {
            c.p[idx] = rnd.next(1, maxP);
        }
    }

    
    for (int i = 1; i <= 2 * n; ++i) {
        if (c.p[i] == 0) c.p[i] = rnd.next(1, maxP);
    }

    
    for (int i = (int)c.pairs.size() - 1; i > 0; --i) {
        int j = rnd.next(0, i);
        swap(c.pairs[i], c.pairs[j]);
    }

    return c;
}

static void outputNon(const GenCase& c) {
    cout << c.n << " " << c.m << "\n";
    for (int i = 1; i <= 2 * c.n; ++i) {
        cout << c.p[i] << (i == 2 * c.n ? '\n' : ' ');
    }
    for (auto [a, b] : c.pairs) {
        cout << a << " " << b << "\n";
    }
    cout << c.t << "\n";
}

static void outputAdp(const GenCase& c) {
    
    
    cout << c.n << " " << c.m << "\n";
    for (int i = 1; i <= 2 * c.n; ++i) {
        cout << c.p[i] << (i == 2 * c.n ? '\n' : ' ');
    }
    for (auto [a, b] : c.pairs) {
        cout << a << " " << b << "\n";
    }
    cout << c.t << "\n";
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);

    string mode = opt<string>("mode", "non");
    int nDefault = opt<int>("n", 1000);
    int mOpt = opt<int>("m", -1);
    int maxP = opt<int>("maxP", 1000);
    int tOpt = opt<int>("t", 0);

    nDefault = max(1, min(1000, nDefault));
    maxP = max(1, min(1000, maxP));

    long long seedVal = atoll(argv[1]);

    GenCase c;
    if (seedVal == 1) c = makeCorner1();
    else if (seedVal == 2) c = makeCorner2();
    else if (seedVal == 3) c = makeCorner3();
    else c = makeRandomCase(seedVal, nDefault, mOpt, maxP, tOpt);

    if (mode == "non") {
        outputNon(c);
    } else if (mode == "adp") {
        outputAdp(c);
    } else {
        ensuref(false, "Unknown --mode, expected 'non' or 'adp'");
    }
    return 0;
}