很板子的二维数点问题:
平面上有 n个点 (xi,yi)。
回答 q 个询问,每个询问给定一个矩形 [X1,X2]×[Y1,Y2],询问矩形里面有多少个点。
第一行两个整数 n,q(1≤n,q≤105)。
接下来 n 行,每行两个整数 xi,yi(1≤xi,yi≤109)。
接下来 q 行,每行四个整 X1,X2,Y1,Y2(1≤X1≤X2≤109,1≤Y1≤Y2≤109)。
用的是离散化+扫描线,把询问离线下来,显然的 [X1,X2]×[Y1,Y2] 的点数等于 [−inf,X2]×[−inf,Y2] 的点数 - [−inf,X1−1]×[−inf,Y2] 的点数 - [−inf,X2]×[−inf,Y1−1] + [−inf,X1−1]×[−inf,Y1−1] 的点数。
然后基于 x 从小到大排序询问,最后双指针来加点,然后查询即可。
数据结构用的是树状数组。
#include <bits/stdc++.h>
using namespace std;
int n, q, x[200005], y[200005], qx1[200005], qy1[200005], qx2[200005], qy2[200005], xx[200005], yy[200005], qans[200005];
vector<int> pts[200005];
bool added[200005];
struct Query {
int x, y, id, tanlihan;
bool operator < (const Query &q) const {
return x < q.x;
}
};
vector<Query> qs;
int t[200005];
void update(int i) { for (int j = i; j <= n; j += (j & (-j))) t[j]++; }
int sum(int i) { int ans = 0; while (i) { ans += t[i]; i -= (i & (-i)); } return ans; }
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; ++i) {
cin >> x[i] >> y[i];
xx[i] = y[i];
yy[i] = y[i];
}
sort(xx+1,xx+n+1);
int cntx=unique(xx+1,xx+n+1)-(xx+1);
sort(yy+1,yy+n+1);
int cnty=unique(yy+1,yy+n+1)-(yy+1);
for(int i=1;i<=n;i++){
x[i]=lower_bound(xx+1,xx+cntx+1,x[i])-xx;
y[i]=lower_bound(yy+1,yy+cnty+1,y[i])-yy;
pts[x[i]].push_back(y[i]);
}
for (int i = 1; i <= q; ++i) {
cin >> qx1[i] >> qx2[i] >> qy1[i] >> qy2[i];
qs.push_back({(int)(lower_bound(xx,xx+cntx+1,qx2[i])-xx), (int)(lower_bound(yy,yy+cnty+1,qy2[i])-yy), i, 1});
qs.push_back({(int)(lower_bound(xx,xx+cntx+1,qx1[i]-1)-xx), (int)(lower_bound(yy,yy+cnty+1,qy2[i])-yy), i, -1});
qs.push_back({(int)(lower_bound(xx,xx+cntx+1,qx2[i])-xx), (int)(lower_bound(yy,yy+cnty+1,qy1[i]-1)-yy), i, -1});
qs.push_back({(int)(lower_bound(xx,xx+cntx+1,qx1[i]-1)-xx), (int)(lower_bound(yy,yy+cnty+1,qy1[i]-1)-yy), i, 1});
}
sort(qs.begin(), qs.end());
int l = 1;
for (auto i : qs) {
while (l <= i.x) {
for (auto j : pts[l]) update(j);
++l;
}
qans[i.id] += i.tanlihan * sum(i.y);
}
for (int i = 1; i <= q; ++i) cout << qans[i] << '\n';
return 0;
}