QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#248128#7627. Phonyucup-team1191#WA 0ms3872kbC++2020.8kb2023-11-11 17:35:492023-11-11 17:35:49

Judging History

你现在查看的是最新测评结果

  • [2023-11-11 17:35:49]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:3872kb
  • [2023-11-11 17:35:49]
  • 提交

answer

/*
    author:  Maksim1744
    created: 11.11.2023 11:17:37
*/

#include "bits/stdc++.h"

using namespace std;

using ll = long long;
using ld = long double;

#define mp   make_pair
#define pb   push_back
#define eb   emplace_back

#define sum(a)     ( accumulate ((a).begin(), (a).end(), 0ll))
#define mine(a)    (*min_element((a).begin(), (a).end()))
#define maxe(a)    (*max_element((a).begin(), (a).end()))
#define mini(a)    ( min_element((a).begin(), (a).end()) - (a).begin())
#define maxi(a)    ( max_element((a).begin(), (a).end()) - (a).begin())
#define lowb(a, x) ( lower_bound((a).begin(), (a).end(), (x)) - (a).begin())
#define uppb(a, x) ( upper_bound((a).begin(), (a).end(), (x)) - (a).begin())

template<typename T>             vector<T>& operator--            (vector<T> &v){for (auto& i : v) --i;            return  v;}
template<typename T>             vector<T>& operator++            (vector<T> &v){for (auto& i : v) ++i;            return  v;}
template<typename T>             istream& operator>>(istream& is,  vector<T> &v){for (auto& i : v) is >> i;        return is;}
template<typename T>             ostream& operator<<(ostream& os,  vector<T>  v){for (auto& i : v) os << i << ' '; return os;}
template<typename T, typename U> pair<T,U>& operator--           (pair<T, U> &p){--p.first; --p.second;            return  p;}
template<typename T, typename U> pair<T,U>& operator++           (pair<T, U> &p){++p.first; ++p.second;            return  p;}
template<typename T, typename U> istream& operator>>(istream& is, pair<T, U> &p){is >> p.first >> p.second;        return is;}
template<typename T, typename U> ostream& operator<<(ostream& os, pair<T, U>  p){os << p.first << ' ' << p.second; return os;}
template<typename T, typename U> pair<T,U> operator-(pair<T,U> a, pair<T,U> b){return mp(a.first-b.first, a.second-b.second);}
template<typename T, typename U> pair<T,U> operator+(pair<T,U> a, pair<T,U> b){return mp(a.first+b.first, a.second+b.second);}
template<typename T, typename U> void umin(T& a, U b){if (a > b) a = b;}
template<typename T, typename U> void umax(T& a, U b){if (a < b) a = b;}

#ifdef HOME
#define SHOW_COLORS
#include "/mnt/c/Libs/tools/print.cpp"
#else
#define show(...) void(0)
#define debugf(fun)   fun
#define debugv(var)   var
#define mclock    void(0)
#define shows     void(0)
#define debug  if (false)
#define OSTREAM(...)    ;
#define OSTREAM0(...)   ;
#endif

namespace segtree {

// This implementation is disgusting, but it seems to work and do it faster than previous version.

template<typename Item>
Item tree_merge(const Item& a, const Item& b) {
    Item i;
    i.update(a, b);
    return i;
}

template<typename Item, bool lazy>
struct Pusher {};

template<typename Item>
struct Pusher<Item, false> {
    void push(const vector<Item>&, int, int, int) {}
    Item ask_on_segment(const vector<Item>& tree, int n, int l, int r) {
        l |= n;
        r |= n;
        Item resl, resr;
        while (l <= r) {
            if (l & 1) {
                resl = tree_merge(resl, tree[l]);
                ++l;
            }
            if (!(r & 1)) {
                resr = tree_merge(tree[r], resr);
                --r;
            }
            l >>= 1;
            r >>= 1;
        }
        return tree_merge(resl, resr);
    }
    void push_point(const vector<Item>&, int, int) {}

    template<typename P>
    int lower_bound(const vector<Item>& tree, int n, int l, P p) {
        Item cur;
        if (p(cur)) return l - 1;
        l |= n;
        int r = n | (n - 1);
        // carefully go up
        while (true) {
            if (p(tree_merge(cur, tree[l]))) {
                break;
            }
            if (l == r) return n;
            if (l & 1) {
                cur = tree_merge(cur, tree[l]);
                ++l;
            }
            l >>= 1;
            r >>= 1;
        }

        // usual descent from l
        while (l < n) {
            if (p(tree_merge(cur, tree[l * 2]))) {
                l = l * 2;
            } else {
                cur = tree_merge(cur, tree[l * 2]);
                l = l * 2 + 1;
            }
        }
        return (l ^ n);
    }

    template<typename P>
    int lower_bound_rev(const vector<Item>& tree, int n, int r, P p) {
        Item cur;
        if (p(cur)) return r + 1;
        r |= n;
        int l = n;
        // carefully go up
        while (true) {
            if (p(tree_merge(tree[r], cur))) {
                break;
            }
            if (l == r) return -1;
            if (!(r & 1)) {
                cur = tree_merge(tree[r], cur);
                --r;
            }
            l >>= 1;
            r >>= 1;
        }

        // usual descent from r
        while (r < n) {
            if (p(tree_merge(tree[r * 2 + 1], cur))) {
                r = r * 2 + 1;
            } else {
                cur = tree_merge(tree[r * 2 + 1], cur);
                r = r * 2;
            }
        }
        return (r ^ n);
    }
};

template<typename Item>
struct Pusher<Item, true> {
    void push(vector<Item>& tree, int ind, int l, int r) {
        tree[ind].push(tree[ind * 2], tree[ind * 2 + 1], l, r);
    }

    Item ask_on_segment(vector<Item>& tree, int n, int l, int r) {
        int vl = 0, vr = n - 1;
        int i = 1;
        Item result;
        while (vl != vr) {
            int m = (vl + vr) / 2;
            if (l > m) {
                push(tree, i, vl, vr);
                i = i * 2 + 1;
                vl = m + 1;
            } else if (r <= m) {
                push(tree, i, vl, vr);
                i = i * 2;
                vr = m;
            } else {
                break;
            }
        }
        if (l == vl && r == vr) {
            return tree[i];
        }
        push(tree, i, vl, vr);
        // left
        {
            int ind = i * 2;
            int L = vl, R = (vl + vr) / 2;
            while (l != L) {
                int m = (L + R) / 2;
                push(tree, ind, L, R);
                if (l <= m) {
                    result = tree_merge(tree[ind * 2 + 1], result);
                    ind *= 2;
                    R = m;
                } else {
                    ind = ind * 2 + 1;
                    L = m + 1;
                }
            }
            result = tree_merge(tree[ind], result);
        }
        // right
        {
            int ind = i * 2 + 1;
            int L = (vl + vr) / 2 + 1, R = vr;
            while (r != R) {
                int m = (L + R) / 2;
                push(tree, ind, L, R);
                if (r > m) {
                    result = tree_merge(result, tree[ind * 2]);
                    ind = ind * 2 + 1;
                    L = m + 1;
                } else {
                    ind = ind * 2;
                    R = m;
                }
            }
            result = tree_merge(result, tree[ind]);
        }
        return result;
    }

    void push_point(vector<Item>& tree, int n, int ind) {
        int l = 0, r = n - 1;
        int i = 1;
        while (l != r) {
            push(tree, i, l, r);
            int m = (l + r) / 2;
            if (ind <= m) {
                r = m;
                i *= 2;
            } else {
                l = m + 1;
                i = i * 2 + 1;
            }
        }
    }

    template<typename P>
    pair<int, Item> _lower_bound(vector<Item>& tree, int l, P p, Item cur, int i, int vl, int vr) {
        if (vl == vr) {
            if (p(tree_merge(cur, tree[i]))) {
                return {vl, tree[i]};
            } else {
                return {vl + 1, tree[i]};
            }
        }

        push(tree, i, vl, vr);
        int m = (vl + vr) / 2;
        if (l > m) {
            return _lower_bound(tree, l, p, cur, i * 2 + 1, m + 1, vr);
        } else if (l <= vl) {
            if (!p(tree_merge(cur, tree[i]))) {
                return {vr + 1, tree_merge(cur, tree[i])};
            }
            if (p(tree_merge(cur, tree[i * 2]))) {
                return _lower_bound(tree, l, p, cur, i * 2, vl, m);
            } else {
                return _lower_bound(tree, l, p, tree_merge(cur, tree[i * 2]), i * 2 + 1, m + 1, vr);
            }
        } else {
            auto [ind, it] = _lower_bound(tree, l, p, cur, i * 2, vl, m);
            if (ind <= m) return {ind, it};
            return _lower_bound(tree, l, p, it, i * 2 + 1, m + 1, vr);
        }
    }

    template<typename P>
    int lower_bound(vector<Item>& tree, int n, int l, P p) {
        Item cur;
        if (p(cur)) return l - 1;
        return _lower_bound(tree, l, p, cur, 1, 0, n - 1).first;
    }

    template<typename P>
    pair<int, Item> _lower_bound_rev(vector<Item>& tree, int r, P p, Item cur, int i, int vl, int vr) {
        if (vl == vr) {
            if (p(tree_merge(tree[i], cur))) {
                return {vl, tree[i]};
            } else {
                return {vl - 1, tree[i]};
            }
        }

        push(tree, i, vl, vr);
        int m = (vl + vr) / 2;
        if (r <= m) {
            return _lower_bound_rev(tree, r, p, cur, i * 2, vl, m);
        } else if (r >= vr) {
            if (!p(tree_merge(tree[i], cur))) {
                return {vl - 1, tree_merge(cur, tree[i])};
            }
            if (p(tree_merge(tree[i * 2 + 1], cur))) {
                return _lower_bound_rev(tree, r, p, cur, i * 2 + 1, m + 1, vr);
            } else {
                return _lower_bound_rev(tree, r, p, tree_merge(tree[i * 2 + 1], cur), i * 2, vl, m);
            }
        } else {
            auto [ind, it] = _lower_bound_rev(tree, r, p, cur, i * 2 + 1, m + 1, vr);
            if (ind > m) return {ind, it};
            return _lower_bound_rev(tree, r, p, it, i * 2, vl, m);
        }
    }

    template<typename P>
    int lower_bound_rev(vector<Item>& tree, int n, int r, P p) {
        Item cur;
        if (p(cur)) return r + 1;
        return _lower_bound_rev(tree, r, p, cur, 1, 0, n - 1).first;
    }
};

template<typename Item, bool lazy = false>
struct Segtree {
    vector<Item> tree;
    Pusher<Item, lazy> pusher;
    int n;
    int n0;

    Segtree(int n = 0) {
        build(n);
    }

    template<typename U>
    Segtree(const vector<U>& v) {
        build(v);
    }

    void build(int n) {
        this->n0 = n;
        while (n & (n - 1)) ++n;
        this->n = n;
        tree.assign(n * 2, {});
    }

    template<typename U>
    void build(const vector<U>& v) {
        build(v.size());
        for (int i = 0; i < v.size(); ++i) {
            tree[n | i].init(v[i], i);
        }
        build();
    }

    void build() {
        for (int i = n - 1; i >= 1; --i) {
            tree[i].update(tree[i * 2], tree[i * 2 + 1]);
        }
    }

    void push(int ind, int l, int r) {
        pusher.push(tree, ind, l, r);
    }

    template<typename T>
    void set(int ind, const T& t) {
        pusher.push_point(tree, n, ind);
        ind |= n;
        tree[ind].init(t, ind ^ n);
        ind >>= 1;
        while (ind) {
            tree[ind].update(tree[ind * 2], tree[ind * 2 + 1]);
            ind >>= 1;
        }
    }

    template<typename T>
    void update(int ind, const T& t) {
        pusher.push_point(tree, n, ind);
        ind |= n;
        tree[ind].update(t, ind ^ n);
        ind >>= 1;
        while (ind) {
            tree[ind].update(tree[ind * 2], tree[ind * 2 + 1]);
            ind >>= 1;
        }
    }

    Item& ith(int ind) {
        static_assert(!lazy, "don't use this method with lazy propagation, unless you're sure you need it");
        return tree[ind | n];
    }

    const Item& root() const {
        return tree[1];
    }

    Item ask(int l, int r) {
        l = max(l, 0);
        r = min(r, n - 1);
        if (l > r) return {};
        return pusher.ask_on_segment(tree, n, l, r);
    }

    template<typename T>
    void modify(int l, int r, const T& t) {
        static_assert(lazy, "lazy must be set to true to use this function");
        l = max(l, 0);
        r = min(r, n - 1);
        if (l > r) return;
        int vl = 0, vr = n - 1;
        int i = 1;
        while (vl != vr) {
            int m = (vl + vr) / 2;
            if (l > m) {
                push(i, vl, vr);
                i = i * 2 + 1;
                vl = m + 1;
            } else if (r <= m) {
                push(i, vl, vr);
                i = i * 2;
                vr = m;
            } else {
                break;
            }
        }
        if (l == vl && r == vr) {
            tree[i].modify(t, l, r);
        } else {
            push(i, vl, vr);
            // left
            {
                int ind = i * 2;
                int L = vl, R = (vl + vr) / 2;
                while (l != L) {
                    int m = (L + R) / 2;
                    push(ind, L, R);
                    if (l <= m) {
                        tree[ind * 2 + 1].modify(t, m + 1, R);
                        ind *= 2;
                        R = m;
                    } else {
                        ind = ind * 2 + 1;
                        L = m + 1;
                    }
                }
                tree[ind].modify(t, L, R);
                ind >>= 1;
                while (ind != i) {
                    tree[ind].update(tree[ind * 2], tree[ind * 2 + 1]);
                    ind >>= 1;
                }
            }
            // right
            {
                int ind = i * 2 + 1;
                int L = (vl + vr) / 2 + 1, R = vr;
                while (r != R) {
                    int m = (L + R) / 2;
                    push(ind, L, R);
                    if (r > m) {
                        tree[ind * 2].modify(t, L, m);
                        ind = ind * 2 + 1;
                        L = m + 1;
                    } else {
                        ind = ind * 2;
                        R = m;
                    }
                }
                tree[ind].modify(t, L, R);
                ind >>= 1;
                while (ind != i) {
                    tree[ind].update(tree[ind * 2], tree[ind * 2 + 1]);
                    ind >>= 1;
                }
            }
            tree[i].update(tree[i * 2], tree[i * 2 + 1]);
        }
        i >>= 1;
        while (i) {
            tree[i].update(tree[i * 2], tree[i * 2 + 1]);
            i >>= 1;
        }
    }

    // first index r such that p(tree.ask(l, r)) == true
    // if p() is true for empty item, return l-1
    // if p() is never true, returns n
    template<typename P>
    int lower_bound(int l, P p) {
        l = max(l, 0);
        if (l >= n0) return n0;
        return min(n0, pusher.lower_bound(tree, n, l, p));
    }

    // similarly to lower_bound, returns first (largest) l such that p(tree.ask(l, r)) == true
    template<typename P>
    int lower_bound_rev(int r, P p) {
        r = min(r, n0 - 1);
        if (r < 0) return -1;
        return pusher.lower_bound_rev(tree, n, r, p);
    }
};

}
using segtree::Segtree;

const ll inf = 5e18 + 1e9;

struct Item {
    ll mx = -inf;
    ll mn = inf;
    ll mod = 0;
    int imx = -1;
    int sm = 0;

    template<typename T>
    void init(const T& t, int ind) {
        mx = mn = t;
        sm = 1;
        imx = ind;
    }

    void update(const Item& a, const Item& b) {
        sm = a.sm + b.sm;
        mx = max(a.mx, b.mx);
        mn = min(a.mn, b.mn);
        if (mx == b.mx)
            imx = b.imx;
        else
            imx = a.imx;
    }

    //// similar to init, but more convenient for doing a[i] += x, implement only if needed
    // template<typename T>
    // void update(const T& t, int ind) {}

    // apply here, save for children
    template<typename T>
    void modify(const T& m, int l, int r) {
        mx += m;
        mn += m;
        mod += m;
    }

    void push(Item& a, Item& b, int l, int r) {
        int m = (l + r) / 2;
        a.modify(mod, l, m);
        b.modify(mod, m + 1, r);
        // reset mod
        mod = 0;
    }
};

OSTREAM(Item, mn, mx, sm);

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

    int n, q;
    ll k;
    cin >> n >> q >> k;
    vector<ll> a(n);
    cin >> a;
    sort(a.begin(), a.end());
    reverse(a.begin(), a.end());
    __int128 sm = 0;
    vector<__int128> after(n, inf);
    for (int i = 0; i < n; ++i) {
        __int128 cur = a[i] / k;
        __int128 here_after = sm - cur * i;
        after[i] = here_after;
        sm += cur;
    }
    show(a);

    vector<int> inds0(n);
    iota(inds0.begin(), inds0.end(), 0);
    sort(inds0.begin(), inds0.end(), [&](int i, int j) {
        return a[i] % k < a[j] % k;
    });
    show(inds0);
    vector<int> inds(n);
    for (int i = 0; i < n; ++i) {
        inds[inds0[i]] = i;
    }

    vector<pair<__int128, int>> when(n);
    for (int i = 0; i < n; ++i) {
        when[i] = mp(after[i], i);
    }
    sort(when.begin(), when.end(), [&](const auto& i, const auto& j) {
        return a[i.second] > a[j.second];
    });
    __int128 curt = 0;
    int iwhen = 0;

    Segtree<Item, true> tree(n);
    assert(when[0].first == 0);
    tree.set(inds[when[0].second], a[when[0].second]);
    ++iwhen;

    auto isplit = [&]() {
        return tree.root().imx;
    };

    while (q--) {
        char tp;
        cin >> tp;
        shows;
        if (tp == 'A') {
            int x;
            cin >> x;
            --x;
            show(tp, x);
            debug {
                for (int i = 0; i < n; ++i) {
                    auto it = tree.ask(i, i);
                    if (it.sm)
                        cerr << it.mx;
                    else
                        cerr << '?';
                    cerr << ' ';
                }
                cerr << endl;
            }
            show(tree.root(), x);
            if (x < tree.root().sm) {
                auto on_pref = tree.ask(0, isplit());
                show(isplit(), on_pref);
                if (x < on_pref.sm) {
                    int ind = tree.lower_bound(0, [&](const auto& it) { return it.sm >= on_pref.sm - x; });
                    show(on_pref.sm - x, ind);
                    cout << tree.ask(ind, ind).mx << '\n';
                } else {
                    x -= on_pref.sm;
                    int onsuf = tree.root().sm - on_pref.sm;
                    int ind = tree.lower_bound(isplit() + 1, [&](const auto& it) { return it.sm >= onsuf - x; });
                    show(x, onsuf, ind);
                    cout << tree.ask(ind, ind).mx << '\n';
                }
            } else {
                cout << a[x] << "\n";
            }
        } else if (tp == 'C') {
            ll t;
            cin >> t;
            show(tp, t);
            while (t) {
                show(t);
                show(when, iwhen, curt);
                ll can = t;
                if (iwhen < when.size()) {
                    can = min((__int128)can, when[iwhen].first - curt);
                }
                show(can);
                show(tree.root());
                debug {
                    for (int i = 0; i < n; ++i) {
                        auto it = tree.ask(i, i);
                        if (it.sm)
                            cerr << it.mx;
                        else
                            cerr << '?';
                        cerr << ' ';
                    }
                    cerr << endl;
                }
                t -= can;
                curt += can;
                tree.modify(0, n-1, -k * (can / tree.root().sm));
                int left = can % tree.root().sm;
                auto on_pref = tree.ask(0, isplit());
                show(isplit(), on_pref, left);
                if (left == on_pref.sm) {
                    tree.modify(0, isplit(), -k);
                } else if (left < on_pref.sm) {
                    int pref_left = tree.lower_bound(0, [&](const auto& it) { return it.sm >= on_pref.sm - left; });
                    show(pref_left);
                    tree.modify(pref_left + 1, isplit(), -k);
                } else {
                    tree.modify(0, isplit(), -k);
                    left -= on_pref.sm;
                    int pref_left = tree.lower_bound(0, [&](const auto& it) { return it.sm >= tree.root().sm - left; });
                    tree.modify(pref_left + 1, n, -k);
                }
                while (iwhen < when.size() && (when[iwhen].first >= curt || a[when[iwhen].second] >= tree.root().mn)) {
                    tree.set(inds[when[iwhen].second], a[when[iwhen].second]);
                    ++iwhen;
                }
            }
        } else {
            assert(false);
        }
    }

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3872kb

input:

3 5 5
7 3 9
A 3
C 1
A 2
C 2
A 3

output:

3
4
-1

result:

ok 3 lines

Test #2:

score: -100
Wrong Answer
time: 0ms
memory: 3532kb

input:

5 8 8
294 928 293 392 719
A 4
C 200
A 5
C 10
A 2
C 120
A 1
A 3

output:

294
120
423
232
-194

result:

wrong answer 2nd lines differ - expected: '200', found: '120'