poj 2318

题目概述

有一长方形,左上顶点坐标(x1,y1),右下顶点坐标(x2,y2),被N条上端点为(up,y1),下端点为(low,y2)的线段分成N+1部分,向长方形中扔M个质点,每个点坐标(x,y),求落在每一部分的点的数量

时限

2000ms/6000ms

输入

每组数据第一行6个整数N,M,x1,y1,x2,y2,其后N行,每行2个整数up,low,再其后M行,每行2个整数x,y,输入到N=0结束

限制

1<=N<=5000;1<=M<=5000;所有线段互不相交;所有质点不会落在线段上;所有质点不会落在长方形外面,但落会落在边界上,也视为落在内部;所有线段按从左到右呈现在输入中

输出

每组输出共N+1行,每行格式为
#: @
#代表长方形的分块序号,从0开始到N结束,@代表该分块中的质点数,冒号后有一空格,两组输出之间有一个空行

样例输入

5 6 0 10 60 0
3 1
4 3
6 8
10 10
15 30
1 5
2 1
2 8
5 5
40 10
7 9
4 10 0 10 100 0
20 20
40 40
60 60
80 80
5 10
15 10
25 10
35 10
45 10
55 10
65 10
75 10
85 10
95 10
0

样例输出

0: 2
1: 1
2: 1
3: 1
4: 0
5: 1

0: 2
1: 2
2: 2
3: 2
4: 2

讨论

计算几何,基本的点线位置关系,搭配二分能够快不少,只是不知为何必须按点线位置关系二分而不能单纯按点的横坐标和线段端点的在一条边上的横坐标二分,如此样例都能过,但会WA

题解状态

220K,63MS,C++,1037B

题解代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f  
#define MAXN 5010
#define memset0(a) memset(a,0,sizeof(a))

int N, M;//隔板数 质点数
int up[MAXN], low[MAXN], cnt[MAXN];//上边界 下边界 每块内质点数
bool f;//控制空行输出
inline int xp(int x1, int y1, int x2, int y2, int x3, int y3)//cross_product 向量积 以第2个点为公共起点 指向第1,3个点 然后前者构成的向量叉乘后者
{
    return (x1 - x2)*(y3 - y2) - (y1 - y2)*(x3 - x2);
}
void fun(int x1, int y1, int x2, int y2)
{
    for (int p = 1; p <= N; p++)
        scanf("%d%d", &up[p], &low[p]);//input//视左边界为第一块隔板
    up[N + 1] = low[N + 1] = x2;//右边界为最后一块隔板
    for (int p = 0; p < M; p++) {
        int x, y;
        scanf("%d%d", &x, &y);//input
        int l = 0, r = N + 1, m = (l + r) / 2;//下面是二分过程
        while (r - l > 1) {
            if (xp(x, y, low[m], y2, up[m], y1) > 0)
                l = m;
            else
                r = m;
            m = (l + r) / 2;
        }
        cnt[m]++;
    }
    if (f)
        printf("\n");//output
    for (int p = 0; p <= N; p++)
        printf("%d: %d\n", p, cnt[p]);//output
    f = 1;//输出间空行
}
int main(void)
{
    //freopen("vs_cin.txt", "r", stdin);
    //freopen("vs_cout.txt", "w", stdout);

    int x1, y1, x2, y2;//长方形左上和右下点坐标
    while (~scanf("%d%d%d%d%d%d", &N, &M, &x1, &y1, &x2, &y2) && N) {//input
        fun(x1, y1, x2, y2);
        memset0(cnt);
    }
}

EOF

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值