Submission #1350371

#TimeUsernameProblemLanguageResultExecution timeMemory
1350371ericl23302Abracadabra (CEOI22_abracadabra)C++20
40 / 100
470 ms83872 KiB
#include <algorithm>
#include <iostream>
#include <map>
#include <numeric>
#include <set>
#include <vector>

using namespace std;

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    vector<int> tree;
    int cnt = 0;
    auto update = [&](int pos, int amt) -> void {
        for (; pos <= cnt; pos += pos & (-pos)) tree[pos] += amt;
    };

    auto sum = [&](int pos) -> int {
        int res = 0;
        for (; pos >= 1; pos -= pos & (-pos)) res += tree[pos];
        return res;
    };

    auto query = [&](int amt) -> int {
        int pos = 0, curSum = 0;
        for (int i = 20; i >= 0; --i) {
            if (pos + (1 << i) <= cnt && curSum + tree[pos + (1 << i)] < amt) {
                curSum += tree[pos + (1 << i)];
                pos += (1 << i);
            }
        }
        return pos + 1;
    };

    int n, q;
    cin >> n >> q;
    vector<int> initial(n + 1);
    for (int i = 1; i <= n; ++i) cin >> initial[i];

    vector<int> nxtLargest(n + 1), stk = {1'000'000'000};
    for (int i = n; i >= 1; --i) {
        while (stk.back() != 1e9 && initial[stk.back()] < initial[i])
            stk.pop_back();
        nxtLargest[i] = stk.back();
        stk.push_back(i);
    }

    set<pair<int, pair<int, int>>> s, allBlocks;
    vector<pair<int, pair<int, int>>> invComp(1);
    map<pair<int, pair<int, int>>, int> comp;
    auto intoBlocks = [&](int l, int r, bool first = false) -> void {
        for (int i = l; i <= r; ++i) {
            int nxt = min(nxtLargest[i] - 1, r);
            s.insert({initial[i], {i, nxt}});
            if (first)
                allBlocks.insert({initial[i], {i, nxt}});
            else
                update(comp[{initial[i], {i, nxt}}], nxt - i + 1);
            i = nxt;
        }
    };

    intoBlocks(1, n, true);
    int curCnt = n;
    while (!s.empty()) {
        while (!s.empty()) {
            auto cur = prev(s.end())->second;
            if (curCnt - cur.second + cur.first - 1 < n / 2) break;
            curCnt -= cur.second - cur.first + 1;
            s.erase(prev(s.end()));
        }
        if (curCnt == n / 2)
            s.clear();
        else if (!s.empty()) {
            auto cur = prev(s.end());
            int mid = cur->second.second - curCnt + n / 2;
            intoBlocks(cur->second.first, mid, true);
            intoBlocks(mid + 1, cur->second.second, true);
            s.erase(cur);
        }
    }

    for (auto& i : allBlocks) invComp.push_back(i);
    cnt = invComp.size() - 1;
    for (int i = 1; i <= cnt; ++i) comp[invComp[i]] = i;

    vector<pair<int, pair<int, int>>> queries;
    for (int i = 0; i < q; ++i) {
        int t, x;
        cin >> t >> x;
        queries.push_back({t, {i, x}});
    }
    sort(queries.begin(), queries.end());
    vector<int> res(q);

    tree.assign(cnt + 1, 0);
    intoBlocks(1, n);
    int idx = 0;
    curCnt = n;
    for (int i = 0; i < n && idx < q; ++i) {
        while (idx < q && (queries[idx].first == i || s.empty())) {
            auto [curQ, curCard] = queries[idx++].second;
            int groupIdx = query(curCard);
            int preSum = sum(groupIdx),
                initialIdx = invComp[groupIdx].second.second;
            for (; preSum > curCard; --preSum, --initialIdx);
            res[curQ] = initial[initialIdx];
        }

        while (!s.empty()) {
            auto cur = prev(s.end())->second;
            if (curCnt - cur.second + cur.first - 1 < n / 2) break;
            curCnt -= cur.second - cur.first + 1;
            s.erase(prev(s.end()));
        }
        if (curCnt == n / 2)
            s.clear();
        else if (!s.empty()) {
            auto cur = prev(s.end());
            update(comp[*cur], cur->second.first - cur->second.second - 1);
            int mid = cur->second.second - curCnt + n / 2;
            intoBlocks(cur->second.first, mid, false);
            intoBlocks(mid + 1, cur->second.second, false);
            s.erase(cur);
        }
    }

    for (auto& i : res) cout << i << '\n';

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