結果

問題 No.3627 Share the Median
コンテスト
ユーザー 👑 loop0919
提出日時 2026-06-10 01:07:24
言語 C++23
(gcc 15.2.0 + boost 1.90.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
(最新)
AC  
(最初)
実行時間 -
コード長 4,849 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,134 ms
コンパイル使用メモリ 351,712 KB
実行使用メモリ 9,544 KB
平均クエリ数 1.00
最終ジャッジ日時 2026-08-14 20:51:01
合計ジャッジ時間 5,666 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge2_0
このコードへのチャレンジ
(要ログイン)
サブタスク 配点 結果
Sample 0 %
Easy 20 % WA * 16
Hard 80 % WA * 24
合計 3 * 0% = 0 点
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <bits/stdc++.h>
using namespace std;

using ll = long long;

const ll INF = (1LL << 62);

struct Item {
    ll val;
    int idx; // original 1-indexed index
};

struct Solver {
    bool isAlice;
    int N, M;
    vector<Item> S;

    int da = 0, db = 0; // discarded count from A / B
    int k_rank = 0;

    int lenA() const {
        return N - da;
    }

    int lenB() const {
        return M - db;
    }

    int myLen() const {
        return isAlice ? lenA() : lenB();
    }

    int myOffset() const {
        return isAlice ? da : db;
    }

    int dummyIndex() const {
        return S[0].idx;
    }

    ll shareIndex(int idx) {
        cout << "share " << idx << '\n';
        cout.flush();

        ll v;
        if (!(cin >> v)) exit(0);
        if (v == -1) exit(0);
        return v;
    }

    void answerAndContinue(ll ans) {
        cout << "answer " << ans << '\n';
        cout.flush();

        int r;
        if (!(cin >> r)) exit(0);
        if (r == -1) exit(0);
    }

    // rank-th value/index in my remaining sequence.
    // rank is 1-indexed.
    pair<int, ll> myRankInfo(int rank) const {
        int len = myLen();
        int off = myOffset();

        if (1 <= rank && rank <= len) {
            const Item &it = S[off + rank - 1];
            return {it.idx, it.val};
        } else {
            return {dummyIndex(), INF};
        }
    }

    // One communication round.
    //
    // Alice sends rankA-th remaining A value.
    // Bob sends rankB-th remaining B value.
    //
    // If that rank does not exist, that player sends a dummy index,
    // and both players logically treat the value as INF.
    pair<ll, ll> exchangeRanks(int rankA, int rankB) {
        bool validA = (1 <= rankA && rankA <= lenA());
        bool validB = (1 <= rankB && rankB <= lenB());

        if (isAlice) {
            auto [idx, myVal] = myRankInfo(rankA);
            ll recv = shareIndex(idx);

            ll aVal = validA ? myVal : INF;
            ll bVal = validB ? recv : INF;
            return {aVal, bVal};
        } else {
            auto [idx, myVal] = myRankInfo(rankB);
            ll recv = shareIndex(idx);

            ll aVal = validA ? recv : INF;
            ll bVal = validB ? myVal : INF;
            return {aVal, bVal};
        }
    }

    // One side is empty.
    // The owner of the answer sends the answer value once.
    void finishFromSide(bool answerIsInAlice, int rank) {
        ll ans = -1;
        int idx = dummyIndex();

        if (isAlice == answerIsInAlice) {
            auto [sendIdx, val] = myRankInfo(rank);
            idx = sendIdx;
            ans = val;
        }

        ll recv = shareIndex(idx);

        if (isAlice != answerIsInAlice) {
            ans = recv;
        }

        answerAndContinue(ans);
    }

    void solveCase() {
        sort(S.begin(), S.end(), [](const Item &a, const Item &b) {
            if (a.val != b.val) return a.val < b.val;
            return a.idx < b.idx;
        });

        da = db = 0;
        k_rank = (N + M + 1) / 2;

        while (true) {
            if (lenA() == 0) {
                finishFromSide(false, k_rank); // answer is in Bob
                return;
            }

            if (lenB() == 0) {
                finishFromSide(true, k_rank); // answer is in Alice
                return;
            }

            if (k_rank <= 3) {
                vector<ll> cand;

                for (int r = 1; r <= k_rank; r++) {
                    auto [av, bv] = exchangeRanks(r, r);
                    if (av < INF) cand.push_back(av);
                    if (bv < INF) cand.push_back(bv);
                }

                sort(cand.begin(), cand.end());
                answerAndContinue(cand[k_rank - 1]);
                return;
            }

            int t = k_rank / 2;
            int p = min(t, lenA());
            int q = min(t, lenB());

            auto [ap, bq] = exchangeRanks(p, q);

            // 重複ありでも、等号時は Alice 側を捨てる、と固定すればよい。
            if (ap <= bq) {
                da += p;
                k_rank -= p;
            } else {
                db += q;
                k_rank -= q;
            }
        }
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T, Q;
    string player;

    cin >> T >> Q;
    cin >> player;

    bool isAlice = (player == "Alice");

    for (int tc = 0; tc < T; tc++) {
        int N, M;
        cin >> N >> M;

        int L = isAlice ? N : M;

        vector<Item> S(L);
        for (int i = 0; i < L; i++) {
            cin >> S[i].val;
            S[i].idx = i + 1;
        }

        Solver solver;
        solver.isAlice = isAlice;
        solver.N = N;
        solver.M = M;
        solver.S = move(S);

        solver.solveCase();
    }

    return 0;
}
0