QOJ.ac

QOJ

Type: Editorial

Status: Open

Posted by: jiangly

Posted at: 2025-12-13 00:30:39

Last updated: 2025-12-13 00:30:56

Back to Problem

题解

把询问分为两类:

  • $X_j+Y_j\ge Z_j$。

    此时只需满足 $S_i\ge X_j$ 和 $T_i\ge Y_j$ 即可。

  • $X_j+Y_j < Z_j$。

    此时,如果学生 $i$ 满足 $S_i+T_i\ge Z_j$,则他至少满足 $S_i\ge X_j$ 和 $T_i\ge Y_j$ 中的一个,分别将不满足其中一个条件的学生数量减去即可。

两类询问都可以对其中一维排序后用树状数组维护。

时间复杂度:$O((N+Q)\log N)$。

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
template<typename T>
struct Fenwick {
    const int n;
    std::vector<T> a;
    Fenwick(int n) : n(n), a(n) {}
    void add(int x, T v) {
        for (int i = x + 1; i <= n; i += i & -i)
            a[i - 1] += v;
    }
    T sum(int x) {
        T ans = 0;
        for (int i = x; i > 0; i -= i & -i)
            ans += a[i - 1];
        return ans;
    }
    T rangeSum(int l, int r) {
        return sum(r) - sum(l);
    }
};
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n, q;
    std::cin >> n >> q;
    std::vector<int> s(n), t(n), sum(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> s[i] >> t[i];
        sum[i] = s[i] + t[i];
    }
    auto vS = s, vT = t, vSum = sum;
    std::sort(vS.begin(), vS.end());
    std::sort(vT.begin(), vT.end());
    std::sort(vSum.begin(), vSum.end());
    vS.erase(std::unique(vS.begin(), vS.end()), vS.end());
    vT.erase(std::unique(vT.begin(), vT.end()), vT.end());
    vSum.erase(std::unique(vSum.begin(), vSum.end()), vSum.end());
    for (int i = 0; i < n; ++i) {
        s[i] = std::lower_bound(vS.begin(), vS.end(), s[i]) - vS.begin();
        t[i] = std::lower_bound(vT.begin(), vT.end(), t[i]) - vT.begin();
        sum[i] = std::lower_bound(vSum.begin(), vSum.end(), sum[i]) - vSum.begin();
    }
    std::vector<std::vector<int>> p1(vS.size() + 1), p2(vSum.size() + 1);
    for (int i = 0; i < n; ++i) {
        p1[s[i]].push_back(i);
        p2[sum[i]].push_back(i);
    }
    std::vector<int> a(q), b(q), c(q);
    std::vector<int> ans(q);
    std::vector<std::vector<int>> e1(vS.size() + 1), e2(vSum.size() + 1);
    for (int i = 0; i < q; ++i) {
        std::cin >> a[i] >> b[i] >> c[i];
        bool flag = a[i] + b[i] >= c[i];
        a[i] = std::lower_bound(vS.begin(), vS.end(), a[i]) - vS.begin();
        b[i] = std::lower_bound(vT.begin(), vT.end(), b[i]) - vT.begin();
        c[i] = std::lower_bound(vSum.begin(), vSum.end(), c[i]) - vSum.begin();
        if (flag) {
            e1[a[i]].push_back(i);
        } else {
            e2[c[i]].push_back(i);
        }
    }
    // if A + B >= C
    [&]() {
        Fenwick<int> tT(vT.size());
        for (int i = vS.size(); i >= 0; --i) {
            for (auto j : p1[i])
                tT.add(t[j], 1);
            for (auto j : e1[i])
                ans[j] = tT.rangeSum(b[j], vT.size());
        }
    }();
    // if A + B < C
    [&]() {
        int cnt = 0;
        Fenwick<int> tS(vS.size()), tT(vT.size());
        for (int i = vSum.size(); i >= 0; --i) {
            for (auto j : p2[i]) {
                ++cnt;
                tS.add(s[j], 1);
                tT.add(t[j], 1);
            }
            for (auto j : e2[i])
                ans[j] = cnt - tS.sum(a[j]) - tT.sum(b[j]);
        }
    }();
    for (int i = 0; i < q; ++i)
        std::cout << ans[i] << "\n";
    return 0;
}

Comments

No comments yet.