제출 #1324949

#제출 시각아이디문제언어결과실행 시간메모리
1324949kirutheesExamination (JOI19_examination)C++20
0 / 100
3095 ms16072 KiB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

struct Student {
    ll s, t;
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, Q;
    cin >> N >> Q;

    vector<Student> stu(N);
    for (int i = 0; i < N; i++)
        cin >> stu[i].s >> stu[i].t;

    // Sort by decreasing S
    sort(stu.begin(), stu.end(), [](auto &a, auto &b) {
        return a.s > b.s;
    });

    struct Query {
        ll A, B, C;
        int id;
        int l, r;
    };

    vector<Query> queries(Q);

    for (int i = 0; i < Q; i++) {
        cin >> queries[i].A >> queries[i].B >> queries[i].C;
        queries[i].id = i;
    }

    // Determine range [l, N-1] where S >= A
    for (int i = 0; i < Q; i++) {
        ll A = queries[i].A;
        int l = lower_bound(stu.begin(), stu.end(), A,
            [](const Student &st, ll val) {
                return st.s > val;
            }) - stu.begin();

        queries[i].l = l;
        queries[i].r = N - 1;
    }

    int block = sqrt(N);

    sort(queries.begin(), queries.end(), [&](auto &a, auto &b) {
        if (a.l / block != b.l / block)
            return a.l < b.l;
        return a.r < b.r;
    });

    multiset<ll> Tvals;
    multiset<ll> Sumvals;

    vector<ll> ans(Q);

    int curL = 0, curR = -1;

    auto add = [&](int idx) {
        Tvals.insert(stu[idx].t);
        Sumvals.insert(stu[idx].s + stu[idx].t);
    };

    auto remove = [&](int idx) {
        Tvals.erase(Tvals.find(stu[idx].t));
        Sumvals.erase(Sumvals.find(stu[idx].s + stu[idx].t));
    };

    for (auto &q : queries) {
        while (curL > q.l) add(--curL);
        while (curR < q.r) add(++curR);
        while (curL < q.l) remove(curL++);
        while (curR > q.r) remove(curR--);

        ll cnt = 0;

        // Count T >= B
        auto itT = Tvals.lower_bound(q.B);
        ll countT = distance(itT, Tvals.end());

        // Count S+T >= C
        auto itS = Sumvals.lower_bound(q.C);
        ll countSum = distance(itS, Sumvals.end());

        // Need both conditions
        // brute intersect by iterating smaller set
        if (countT < countSum) {
            for (auto it = itT; it != Tvals.end(); ++it) {
                ll t = *it;
                // need S >= A already ensured by range
                // find matching student with sum >= C
                // approximate by checking
                // (safe because N <= 1e5 and Mo blocks limit active size)
                for (int i = curL; i <= curR; i++) {
                    if (stu[i].t == t &&
                        stu[i].s + stu[i].t >= q.C)
                        cnt++;
                }
            }
        } else {
            for (auto it = itS; it != Sumvals.end(); ++it) {
                ll sum = *it;
                for (int i = curL; i <= curR; i++) {
                    if (stu[i].s + stu[i].t == sum &&
                        stu[i].t >= q.B)
                        cnt++;
                }
            }
        }

        ans[q.id] = cnt;
    }

    for (int i = 0; i < Q; i++)
        cout << ans[i] << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...