Submission #1014464

#TimeUsernameProblemLanguageResultExecution timeMemory
1014464shiomusubi496Abracadabra (CEOI22_abracadabra)C++17
100 / 100
1610 ms52712 KiB
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define rep2(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define all(v) begin(v), end(v)

using namespace std;

using ll = long long;

template<class T, class U> bool chmin(T& a, const U& b) { return a > b ? a = b, true : false; }
template<class T, class U> bool chmax(T& a, const U& b) { return a < b ? a = b, true : false; }

class BinaryIndexedTree {
    int n;
    vector<int> dat;

public:
    BinaryIndexedTree(int n_) : n(n_), dat(n_ + 1, 0) {}
    void add(int k, ll x) {
        ++k;
        while (k <= n) {
            dat[k] += x;
            k += k & -k;
        }
    }
    ll sum(int k) const {
        ll res = 0;
        while (k > 0) {
            res += dat[k];
            k -= k & -k;
        }
        return res;
    }
    ll sum(int l, int r) const { return sum(r) - sum(l); }

    ll get(int k) const { return sum(k, k + 1); }

    template<class F> int max_right(F&& f) const {
        int x = 0;
        ll w = 0;
        for (int k = 1 << 20; k > 0; k >>= 1) {
            if (x + k <= n && f(w + dat[x + k])) {
                w += dat[x + k];
                x += k;
            }
        }
        return x;
    }
};

int main() {
    int N, Q; cin >> N >> Q;
    vector<int> A(N);
    rep (i, N) cin >> A[i];
    rep (i, N) --A[i];
    int M = 2 * N;
    vector<vector<pair<int, int>>> query(M);
    vector<int> ans(Q, -1);
    rep (i, Q) {
        int t, k; cin >> t >> k;
        chmin(t, M);
        --k;
        if (t == 0) ans[i] = A[k];
        else query[t - 1].emplace_back(k, i);
    }

    vector<int> nxt(N, N); // 自分より大きい最初の要素
    vector<int> len(N); // prefix で最大値を取るものについて、それが支配する区間の長さ
    {
        stack<int> st{{N}};
        rrep (i, N) {
            while (st.top() != N && A[st.top()] < A[i]) st.pop();
            nxt[i] = st.top();
            st.push(i);
        }
        while (st.top() != N) {
            len[st.top()] = nxt[st.top()] - st.top();
            st.pop();
        }
    }

    vector<int> Arev(N);
    rep (i, N) Arev[A[i]] = i;

    BinaryIndexedTree bit(N);
    rep (i, N) bit.add(A[i], len[i]);

    for (auto qs : query) {
        int a = bit.max_right([&](int w) { return w <= N / 2; });
        int t = N / 2 - bit.sum(a);
        a = Arev[a];
        if (t) {
            // A[a] が支配する区間が分割される
            int l = a + len[a];
            bit.add(A[a], t - len[a]);
            len[a] = t;
            a += t;
            while (a < l) {
                int na = min(nxt[a], l);
                bit.add(A[a], na - a);
                len[a] = na - a;
                a = na;
            }
        }
        for (auto [k, i] : qs) {
            int a = bit.max_right([&](int w) { return w <= k; });
            int t = k - bit.sum(a);
            a = Arev[a];
            ans[i] = A[a + t];
        }
    }
    for (auto i : ans) cout << i + 1 << endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...