poj 2318 TOYS 点与矩形的关系

题目链接

题意

有一个矩形盒子,\(n(n\leq 5e4)\)条线段将其分成了\(n+1\)个区域(每条线段的两个端点分别在矩形的上边和下边,且线段互不相交)。现向盒子中扔\(m(m\leq 5e4)\)个玩具,问最终盒子的\(n+1\)个区域中各有多少玩具。数据保证玩具不会扔在线段上。

思路

假设玩具\(P\)在第\(i\)个区域,其左边为第\(i\)条线段\(A_1B_1\),右边为第\(i+1\)条线段\(A_2B_2\)\(A\)在上边,\(B\)在下边),则有$$\overrightarrow{PA_1}\times\overrightarrow{PB_1}\gt 0 且 \overrightarrow{PA_2}\times\overrightarrow{PB_2}\lt 0$$
并且左边的叉积都大于\(0\),右边都小于\(0\).

因此可以二分查找\(P\)的位置。

也可以先对玩具的横坐标用\(lower\_bound\)确定下来一个小范围,再在这个小范围内二分(直接查找也可以,因为这个范围应该很小)。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 5010
int up[maxn], down[maxn], ans[maxn], n, m;
using namespace std;
typedef long long LL;
LL vec(LL x1, LL y1, LL x2, LL y2, LL x0, LL y0) {
    return (x1-x0) * (y2-y0) - (x2-x0) * (y1-y0);
}
void work() {
    memset(ans, 0, sizeof ans);
    int x1, y1, x2, y2;
    scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
    for (int i = 1; i <= n; ++i) scanf("%d%d", &up[i], &down[i]);
    up[0] = down[0] = x1, up[n+1] = down[n+1] = x2;
    while (m--) {
        int x, y;
        scanf("%d%d", &x, &y);
        int p2 = lower_bound(down, down+n+1, x) - down,
            p1 = lower_bound(up, up+n+1, x) - up;
        if (p1 == p2) { ++ans[p1-1]; continue; }
        if (p1 > p2) swap(p1, p2);
        for (int i = p1; i <= p2; ++i) {
            if (vec(up[i], y1, down[i], y2, x, y) < 0) { ++ans[i-1]; break; }
        }
    }
    for (int i = 0; i <= n; ++i) printf("%d: %d\n", i, ans[i]);
    printf("\n");
}
int main() {
    while (scanf("%d", &n) && n) work();
    return 0;
}
posted @ 2017-10-06 21:37  救命怀  阅读(156)  评论(0编辑  收藏  举报