Basketball tournament

  • + 0 comments

    pragma GCC optimize("O3")

    pragma GCC optimize("unroll-loops")

    pragma GCC target("avx2")

    include

    using namespace std;

    define rep(i,n) for(int i=0;i

    define per(i,n) for(int i=n-1;i>=0;i--)

    define rng(i,c,n) for(int i=c;i

    define fi first

    define se second

    define pb push_back

    define sz(a) (int)(a.size())

    define all(a) a.begin(),a.end() define _3Wcdivh ios::sync_with_stdio(0),cin.tie(0)

    typedef long long ll; typedef vector vi; typedef pair pii;

    void print() { cout << '\n'; } template void print(const h& v, const t&... u) { cout << v << ' '; print(u...); }

    const int N = (int) 3e5 + 1; const ll LINF = (ll) 1e18 + 123;

    struct DSU { int n; int dsu[N]; int leftmost[N]; int rightmost[N];

    void init(int n_) {
        n = n_ + 1;
        rep(i, n) {
            dsu[i] = -1;
            leftmost[i] = i;
            rightmost[i] = i;
        }
    }
    
    int get(int v) {
        if (dsu[v] == v) return v;
        return (dsu[v] = get(dsu[v]));
    }
    
    void unite(int u, int v) {
        u = get(u);
        v = get(v);
        dsu[u] = v;
        leftmost[v] = min(leftmost[v], leftmost[u]);
        rightmost[v] = max(rightmost[v], rightmost[u]);
    }
    
    bool is_enabled(int v) { return dsu[v] != -1; }
    
    pii get_segment(int v) {
        if (!is_enabled(v)) return {-1, -1};
        v = get(v);
        return {leftmost[v], rightmost[v]};
    }
    
    void enable(int v) {
        dsu[v] = v;
        if (v - 1 >= 0 && dsu[v - 1] != -1) unite(v - 1, v);
        if (v + 1 < n && dsu[v + 1] != -1) unite(v, v + 1);
    }
    

    };

    class MinTree { public: void init(int n_) { n = n_ + 1; fill(tree, tree + 4 * n, LINF); }

    void update(int index, ll value) {
        update(0, 0, n, index, value);
    }
    
    ll get(int l, int r) {
        return get(0, 0, n, l, r + 1);
    }
    

    private: int n; ll tree[4 * N];

    void update(int i, int tl, int tr, int index, ll value) {
        if (tl == tr - 1) {
            tree[i] = min(tree[i], value);
            return;
        }
        int tm = (tl + tr) / 2;
        if (index < tm) update(2 * i + 1, tl, tm, index, value);
        else update(2 * i + 2, tm, tr, index, value);
        tree[i] = min(tree[2 * i + 1], tree[2 * i + 2]);
    }
    
    ll get(int i, int tl, int tr, int l, int r) {
        if (tl >= r || tr <= l) return LINF;
        if (l <= tl && tr <= r) return tree[i];
        int tm = (tl + tr) / 2;
        return min(get(2 * i + 1, tl, tm, l, r), get(2 * i + 2, tm, tr, l, r));
    }
    

    };

    struct Query { int l, r; ll x; int id; };

    int n, m; ll h[N]; ll pref[N]; Query queries[N]; MinTree tree; DSU dsu; ll ans[N];

    ll get_sum(int l, int r) { return pref[r] - pref[l - 1]; }

    void slv() { cin >> n >> m; vector> heights(n); tree.init(n); rng(i, 1, n + 1) { cin >> h[i]; heights[i - 1] = {h[i], i}; pref[i] = pref[i - 1] + h[i]; tree.update(i, -h[i]); }

    rep(i, m) {
        cin >> queries[i].l >> queries[i].r >> queries[i].x;
        queries[i].id = i;
        ans[i] = LINF;
        int left, right;
    
        left = queries[i].l - 1;
        right = queries[i].r + 1;
        while (right - left > 1) {
            int mid = (left + right) / 2;
            int length = mid - queries[i].l + 1;
            if (get_sum(queries[i].l, mid) * 2 * length >= queries[i].x) right = mid;
            else left = mid;
        }
    
        if (right != queries[i].r + 1) ans[i] = min(ans[i], -tree.get(queries[i].l, right));
    
        left = queries[i].l - 1;
        right = queries[i].r + 1;
        while (right - left > 1) {
            int mid = (left + right) / 2;
            int length = queries[i].r - mid + 1;
            if (get_sum(mid, queries[i].r) * 2 * length >= queries[i].x) left = mid;
            else right = mid;
        }
        if (left != queries[i].l - 1) {
            ans[i] = min(ans[i], -tree.get(left, queries[i].r));
            queries[i].r = right - 1;
        }
    }
    
    sort(all(heights));
    dsu.init(n);
    vector<pair<ll, pii>> events;
    rep(i, n) {
        int pos = heights[i].se;
        dsu.enable(pos);
        pii segment = dsu.get_segment(pos);
        int left = segment.fi;
        int right = segment.se;
        int length = right - left + 1;
        ll value = get_sum(left, right) * 2 * length;
        events.pb({value, {left, h[pos]}});
    }
    
    sort(all(events), [](const auto& x, const auto& y) { return x.fi > y.fi; });
    sort(queries, queries + m, [](const auto& x, const auto& y) { return x.x > y.x; });
    
    tree.init(n);
    int ptr = 0;
    rep(i, m) {
        while (ptr < n && events[ptr].fi >= queries[i].x) {
            tree.update(events[ptr].se.fi, events[ptr].se.se);
            ptr++;
        }
        int id = queries[i].id;
        if (ans[id] == LINF) continue;
        ans[id] = min(ans[id], tree.get(queries[i].l, queries[i].r));
    }
    
    rep(i, m) cout << (ans[i] == LINF ? -1 : ans[i]) << "\n";
    

    }

    int main() { _3Wcdivh; slv(); return 0; }