QOJ.ac

QOJ

IDSubmission IDProblemHackerOwnerResultSubmit timeJudge time
#448#251024#7627. PhonyKKT89KKT89Failed.2023-11-14 09:10:372023-11-14 09:10:38

Details

Extra Test:

Standard Program Time Limit Exceeded

input:

13 14 1
1 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000 1000000000000000000
C 1000000000000000000
A 1
A 2
A 3
A 4
A 5
A 6
A 7
...

output:


result:


IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#251024#7627. PhonyKKT89AC ✓275ms16156kbC++175.9kb2023-11-14 04:21:312023-11-14 04:21:32

answer

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

// 0-indexed
template<typename T>
struct BIT{
    int n;
    vector<T> bit,ary;
    BIT(int n = 0) : n(n),bit(n+1),ary(n) {}
    T operator[](int k) {
        return ary[k];
    }
    // [0, i)
    T sum(int i) {
        T res = 0;
        for (; i > 0; i -= (i&-i)) {
            res += bit[i];
        }
        return res;
    }
    // [l, r)
    T sum(int l, int r) {
        return sum(r) - sum(l);
    }
    void add(int i, T a) {
        ary[i] += a;
        i++;
        for (; i <= n; i += (i&-i)) {
            bit[i] += a;
        }
    }
    int lower_bound(T k) { // k <= sum(res)
        if (k <= 0) return 0;
        int res = 0, i = 1;
        while ((i << 1) <= n) i <<= 1;
        for (; i ; i >>= 1) {
            if (res+i <= n and bit[res+i] < k) {
                k -= bit[res += i];
            }
        }
        return res;
    }

    // The 2nd UC Stage 9: Qinhuangdao - I
    // 円環状で見たときに bit[i]+bit[i-1]+...+bit[j] を求める
    T sum_cyc(int i, int j) {
        if (j <= i) return sum(j, i+1);
        else return sum(0, i+1) + sum(j, n);
    }
    // The 2nd UC Stage 9: Qinhuangdao - I
    // 円環状で見たときに bit[i]+bit[i-1]+...+bit[j] >= k となる最近の j と左辺の総和を求める
    // 雑にlog2つ
    pair<int, T> lower_bound_cyc(int j, T k) {
        T prefix = sum(j+1);
        if (prefix < k) {
            k -= prefix;
            int l = 0, r = n;
            while (r-l > 1) {
                int mid = (l+r)/2;
                T s = sum(mid, n);
                if (s >= k) {
                    l = mid;
                }
                else {
                    r = mid;
                }
            }
            return {l, prefix+sum(l,n)};
        }
        else {
            int l = 0, r = j+1;
            while (r-l > 1) {
                int mid = (l+r)/2;
                T s = sum(mid, j+1);
                if (s >= k) {
                    l = mid;
                }
                else {
                    r = mid;
                }
            }
            return {l, sum(l, j+1)};
        }
    }
};

bool de = false;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,q; cin >> n >> q;
    ll K; cin >> K;
    vector<ll> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    if (a[0] == 4288386677374751) de = true;
    sort(a.rbegin(), a.rend());
    vector<ll> z(n);
    for (int i = 0; i < n; ++i) {
        z[i] = a[i]%K;
    }
    sort(z.begin(), z.end());
    z.erase(unique(z.begin(), z.end()), z.end());

    int m = z.size();
    int sz = 0;
    BIT<ll> bit(m);
    auto add = [&](int i) -> void {
        sz += 1;
        bit.add(i, 1);
    };
    vector<ll> md(n);
    for (int i = 0; i < n; ++i) {
        md[i] = lower_bound(z.begin(), z.end(), a[i]%K) - z.begin();
        if (a[0]-a[i] < K) {
            add(md[i]);
        }
    }

    ll pos = md[0];
    ll cnt = 0;
    ll mx = a[0];
    ll nx = 0;

    auto calNext = [&]() -> void {
        if (sz >= n) {
            return;
        }
        else {
            ll dif = z[pos]-z[md[sz]];
            if (dif < 0) dif += K;
            nx = bit.sum_cyc(pos, md[sz]);

            ll uo = mx-dif;
            nx += (ll)(uo-a[sz]-K)/K*(ll)sz;
        }
    };

    calNext();

    while (q--) {
        char c; cin >> c;
        ll in; cin >> in;
        if (c == 'A') {
            int x = in;
            ll res;
            if (sz < x) {
                res = a[x-1];
            }
            else {
                // 最大値との差分を返すように
                auto findKth = [&](int i, int k, int cnt) -> ll {
                    if (bit[i]-cnt >= k) return 0;
                    if (sz-cnt < k) return K;

                    k += cnt;
                    auto p = bit.lower_bound_cyc(i, k);
                    ll dif = z[i]-z[p.first];
                    if (dif < 0) dif += K;
                    return dif;
                };
                ll dif = findKth(pos, x, cnt);
                res = mx-dif;
            }
            cout << res << "\n";
        }
        else {
            auto update = [&]() -> void {
                if (pos) {
                    mx -= z[pos]-z[pos-1];
                    pos -= 1;
                    cnt = 0;
                }
                else {
                    mx -= z[0]-z[m-1]+K;
                    pos = m-1;
                    cnt = 0;
                }
            };

            ll t = in;
            while (sz < n and t >= nx) {
                t -= nx;
                mx = a[sz]+K;
                pos = md[sz];
                ll cp = a[sz];
                while (sz < n and a[sz] == cp) {
                    add(md[sz]);
                }
                update();
                calNext();
            }

            nx -= t;
            ll u = t/sz;
            mx -= u*K;
            t -= u*sz;

            if (bit[pos]-cnt >= t) {
                cnt += t;
            }
            else {
                t -= (bit[pos]-cnt);
                update();

                auto p = bit.lower_bound_cyc(pos, t);
                ll dif = z[pos] - z[p.first];
                if (dif < 0) dif += K;
                mx -= dif;
                pos = p.first;
                cnt = t-(p.second-bit[pos]);
            }
        }
    }
}