Submission #1363126

#TimeUsernameProblemLanguageResultExecution timeMemory
1363126ghwlfkeArchery (IOI09_archery)C++17
100 / 100
283 ms45012 KiB
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

struct SegTree {
    int n;
    vector<long long> mn, lazy;

    SegTree() : n(0) {}

    SegTree(const vector<long long>& a) {
        init(a);
    }

    void init(const vector<long long>& a) {
        n = (int)a.size();
        mn.assign(4 * n, 0);
        lazy.assign(4 * n, 0);
        build(1, 0, n - 1, a);
    }

    void build(int v, int l, int r, const vector<long long>& a) {
        if (l == r) {
            mn[v] = a[l];
            return;
        }

        int m = (l + r) >> 1;
        build(v << 1, l, m, a);
        build(v << 1 | 1, m + 1, r, a);
        mn[v] = min(mn[v << 1], mn[v << 1 | 1]);
    }

    void push(int v) {
        if (lazy[v] == 0) return;

        long long x = lazy[v];
        int lch = v << 1;
        int rch = v << 1 | 1;

        mn[lch] += x;
        lazy[lch] += x;
        mn[rch] += x;
        lazy[rch] += x;

        lazy[v] = 0;
    }

    void rangeAdd(int ql, int qr, long long val) {
        rangeAdd(1, 0, n - 1, ql, qr, val);
    }

    void rangeAdd(int v, int l, int r, int ql, int qr, long long val) {
        if (qr < l || r < ql) return;

        if (ql <= l && r <= qr) {
            mn[v] += val;
            lazy[v] += val;
            return;
        }

        push(v);
        int m = (l + r) >> 1;

        rangeAdd(v << 1, l, m, ql, qr, val);
        rangeAdd(v << 1 | 1, m + 1, r, ql, qr, val);

        mn[v] = min(mn[v << 1], mn[v << 1 | 1]);
    }

    long long rangeMin(int ql, int qr) {
        return rangeMin(1, 0, n - 1, ql, qr);
    }

    long long rangeMin(int v, int l, int r, int ql, int qr) {
        if (qr < l || r < ql) return (long long)4e18;

        if (ql <= l && r <= qr) return mn[v];

        push(v);
        int m = (l + r) >> 1;

        return min(
            rangeMin(v << 1, l, m, ql, qr),
            rangeMin(v << 1 | 1, m + 1, r, ql, qr)
        );
    }

    int findFirstLess(int ql, int qr, long long val) {
        return findFirstLess(1, 0, n - 1, ql, qr, val);
    }

    int findFirstLess(int v, int l, int r, int ql, int qr, long long val) {
        if (qr < l || r < ql || mn[v] >= val) return -1;

        if (l == r) return l;

        push(v);
        int m = (l + r) >> 1;

        int left = findFirstLess(v << 1, l, m, ql, qr, val);
        if (left != -1) return left;

        return findFirstLess(v << 1 | 1, m + 1, r, ql, qr, val);
    }
};

struct Parking {
    int M, L;
    SegTree seg;

    Parking() : M(0), L(0) {}

    Parking(int m, const vector<int>& cnt) {
        init(m, cnt);
    }

    void init(int m, const vector<int>& cnt) {
        M = m;
        L = 3 * M;

        vector<long long> pref(L + 1, 0);

        for (int k = 1; k <= L; ++k) {
            int idx = (k - 1) % M + 1;
            pref[k] = pref[k - 1] + (long long)cnt[idx] - 1;
        }

        seg.init(pref);
    }

    void addChip(int pos, int delta) {
        for (int p = pos; p <= L; p += M) {
            seg.rangeAdd(p, L, delta);
        }
    }

    int firstFree(int pos) {
        int E = M + pos - 1;

        long long base = seg.rangeMin(E - M, E);
        int q = seg.findFirstLess(E + 1, E + M, base);

        return (q - 1) % M + 1;
    }
};

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

    int N;
    long long R;
    cin >> N >> R;

    int S;
    cin >> S;

    vector<int> better(2 * N, 0); // 1..2N-1

    for (int i = 1; i <= 2 * N - 1; ++i) {
        int x;
        cin >> x;
        better[i] = (x < S) ? 1 : 0;
    }

    int K = S - 1;

    if (K == 0) {
        cout << N << '\n';
        return 0;
    }

    int bestStart = 1;
    int bestFinal = N + 1;

    auto consider = [&](int start, int fin) {
        if (fin < bestFinal || (fin == bestFinal && start > bestStart)) {
            bestFinal = fin;
            bestStart = start;
        }
    };

    if (K <= N) {
        vector<int> c(N + 1, 0);

        c[1] = better[1];

        for (int i = 2; i <= N; ++i) {
            c[i] = better[2 * i - 2] + better[2 * i - 1];
        }

        set<int> positive;

        for (int i = 1; i <= N; ++i) {
            if (c[i] > 0) positive.insert(i);
        }

        vector<int> phaseCnt(N + 1, 0);

        auto addLowToArray = [&](int target, int cnt, int delta) {
            if (target == 1) {
                phaseCnt[1] += delta * cnt;
            } else {
                if (cnt >= 1) phaseCnt[target] += delta;
                if (cnt >= 2) {
                    int nxt = (target == N) ? 1 : target + 1;
                    phaseCnt[nxt] += delta;
                }
            }
        };

        for (int i = 1; i <= N; ++i) {
            addLowToArray(i, c[i], +1);
        }

        int station = *positive.begin();
        phaseCnt[station]--;

        Parking park(N, phaseCnt);

        auto applyLow = [&](int target, int cnt, int delta) {
            if (target == 1) {
                if (cnt != 0) park.addChip(1, delta * cnt);
            } else {
                if (cnt >= 1) park.addChip(target, delta);
                if (cnt >= 2) {
                    int nxt = (target == N) ? 1 : target + 1;
                    park.addChip(nxt, delta);
                }
            }
        };

        auto changeC = [&](int target, int newValue) {
            applyLow(target, c[target], -1);

            if (c[target] > 0) positive.erase(target);

            c[target] = newValue;

            if (c[target] > 0) positive.insert(target);

            applyLow(target, c[target], +1);
        };

        long long Rmod = R % N;

        for (int t = 1; t <= N; ++t) {
            int firstBetterTarget = *positive.begin();

            int release;

            if (t < firstBetterTarget) {
                release = firstBetterTarget;
            } else if (t == 1) {
                release = 1;
            } else {
                release = t + c[t];
            }

            int releasePhase = (release - 1) % N + 1;
            int phi = park.firstFree(releasePhase);

            int eMod = phi % N;
            int d = (int)((Rmod - eMod + N) % N);
            int finalTarget = N - d;

            consider(t, finalTarget);

            if (t < N && better[2 * t] == 1) {
                int oldStation = *positive.begin();

                park.addChip(oldStation, +1);

                changeC(t, c[t] + 1);
                changeC(t + 1, c[t + 1] - 1);

                int newStation = *positive.begin();

                park.addChip(newStation, -1);
            }
        }
    } else {
        int M = N - 1;

        auto mapTarget = [&](int target) -> int {
            if (target == 1) return 1;
            return N - target + 1;
        };

        auto targetFromSlot = [&](int slot) -> int {
            return N - slot + 1;
        };

        vector<int> phaseCnt(M + 1, 0);

        auto addWorse = [&](int target, int bit) {
            if (bit == 0) {
                phaseCnt[mapTarget(target)]++;
            }
        };

        addWorse(1, better[1]);

        for (int i = 2; i <= N; ++i) {
            addWorse(i, better[2 * i - 2]);
            addWorse(i, better[2 * i - 1]);
        }

        Parking park(M, phaseCnt);

        for (int t = 1; t <= N; ++t) {
            int pref = mapTarget(t);
            int slot = park.firstFree(pref);
            int finalTarget = targetFromSlot(slot);

            consider(t, finalTarget);

            if (t < N && better[2 * t] == 0) {
                park.addChip(mapTarget(t + 1), -1);
                park.addChip(mapTarget(t), +1);
            }
        }
    }

    cout << bestStart << '\n';

    return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...