听灌多,用扫描线做二维数点
  • 板块灌水区
  • 楼主CuteChat
  • 当前回复2
  • 已保存回复10
  • 发布时间2024/5/27 16:47
  • 上次更新2024/5/27 19:58:50
查看原帖
听灌多,用扫描线做二维数点
726525
CuteChat楼主2024/5/27 16:47

很板子的二维数点问题:

平面上有 nn 个点 (xi,yi)(xi,yi)。

回答 qq 个询问,每个询问给定一个矩形 [X1,X2]×[Y1,Y2][X_1,X_2]×[Y_1,Y_2],询问矩形里面有多少个点。

第一行两个整数 n,q(1≤n,q≤105)n,q(1≤n,q≤10^5)。

接下来 nn 行,每行两个整数 xi,yi(1≤xi,yi≤109)x_i,y_i(1≤x_i,y_i≤10^9)。

接下来 qq 行,每行四个整 X1,X2,Y1,Y2(1≤X1≤X2≤109,1≤Y1≤Y2≤109)X_1,X_2,Y_1,Y_2(1≤X_1≤X_2≤10^9,1≤Y_1≤Y_2≤10^9)。

用的是离散化+扫描线,把询问离线下来,显然的 [X1,X2]×[Y1,Y2][X_1,X_2]×[Y_1,Y_2] 的点数等于 [−inf⁡,X2]×[−inf⁡,Y2][-\inf,X_2]×[-\inf,Y_2] 的点数 - [−inf⁡,X1−1]×[−inf⁡,Y2][-\inf,X_1-1]×[-\inf,Y_2] 的点数 - [−inf⁡,X2]×[−inf⁡,Y1−1][-\inf,X_2]×[-\inf,Y_1-1] + [−inf⁡,X1−1]×[−inf⁡,Y1−1][-\inf,X_1-1]×[-\inf,Y_1-1] 的点数。

然后基于 xx 从小到大排序询问,最后双指针来加点,然后查询即可。

数据结构用的是树状数组。

#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;	
}
2024/5/27 16:47
加载中...