矩形區域由 n 條線段(連接上邊 (x1, y1) 與下邊 (x2, y2))劃分為 n+1 個縱向分區。給 m 個玩具座標,統計每個分區內的玩具數量。線段不相交,n ≤ 5000, m ≤ 5000。
(x, y),需找到它位於哪兩條線段之間。利用叉積判斷點在線段左側還是右側。AB = (x2 - x1, y2 - y1), AP = (x - x1, y - y1),叉積 AB × AP > 0 表示 P 在線段左側。#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5005;
struct Line { int x1, x2; } L[MAXN];
int cnt[MAXN];
// 叉積判斷點 (x,y) 相對線段 i 的位置:>0 左側, <0 右側
int cross(int i, int x, int y) {
int x1 = L[i].x1, x2 = L[i].x2;
return (x2 - x1) * (y - y1) - (x - x1) * (y2 - y1);
}
int main() {
int n, m, x1, y1, x2, y2;
while (scanf("%d", &n), n) {
scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
for (int i = 1; i <= n; ++i) scanf("%d%d", &L[i].x1, &L[i].x2);
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < m; ++i) {
int x, y; scanf("%d%d", &x, &y);
if (cross(1, x, y) < 0) { cnt[0]++; continue; }
if (cross(n, x, y) > 0) { cnt[n]++; continue; }
int l = 1, r = n;
while (r - l > 1) {
int mid = (l + r) >> 1;
if (cross(mid, x, y) < 0) r = mid;
else l = mid;
}
cnt[l]++;
}
for (int i = 0; i <= n; ++i) printf("%d: %d\n", i, cnt[i]);
if (n) printf("\n");
}
return 0;
}
y1, y2,可預先計算 dy = y2 - y1。r - l > 1 終止,最終 l 為目標分區左邊線段索引。