把询问分为两类:
$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;
}