题目概述
有一长方形,左上顶点坐标(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;所有线段互不相交;所有质点不会落在线段上;所有质点不会落在长方形外面,但落会落在边界上,也视为落在内部;
输出
每组输出第一行为字符串Box,其后若干行,每行格式为
#: @
其中#为质点数,@为含有#个质点的分块数,若分块数@为0,则该行不输出,输出按质点数#升序排列
样例输入
4 10 0 10 100 0
20 20
80 80
60 60
40 40
5 10
15 10
95 10
25 10
65 10
75 10
35 10
45 10
55 10
85 10
5 6 0 10 60 0
4 3
15 30
3 1
6 8
10 10
2 1
2 8
1 5
5 5
40 10
7 9
0
样例输出
Box
2: 5
Box
1: 4
2: 1
讨论
计算几何,和poj 2318几乎一样,考察点线位置关系,以及一点二分思想
题解状态
176K,0MS,C++,1323B
题解代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 1010
#define memset0(a) memset(a,0,sizeof(a))
struct item//隔板的结构
{
int up, low;//上下端点横坐标
}items[MAXN];//隔板原始数据
int cnt[MAXN], cnt2[MAXN];//每个分块所含质点数 含相同质点数的分块数
bool pred(item a, item b)//poj不支持c++11的lambda表达式 因而单独拆出
{
return a.up < b.up;//既然不相交 按上下端点位置判断隔板位置都一样
}
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 N, int M, int x1, int y1, int x2, int y2)
{
for (int p = 1; p <= N; p++)//0下标留给长方形左边界
scanf("%d%d", &items[p].up, &items[p].low);//input
items[N + 1].up = items[N + 1].low = x2;//长方形右边界也视为隔板之一
sort(items + 1, items + N + 1, pred);//与poj 2318相比 隔板是无序出现的 需额外排序
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, items[m].low, y2, items[m].up, y1) > 0)
l = m;
else
r = m;
m = (l + r) / 2;
}
cnt[m]++;
}
int most = 0;//记录单块所含最多质点数 作为循环边界
for (int p = 0; p <= N; p++) {
cnt2[cnt[p]]++;
most = max(most, cnt[p]);
}
printf("Box\n");//output
for (int p = 1; p <= most; p++)
if (cnt2[p])
printf("%d: %d\n", p, cnt2[p]);//output
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);
int N, M, x1, y1, x2, y2;
while (~scanf("%d%d%d%d%d%d", &N, &M, &x1, &y1, &x2, &y2) && N) {//input
fun(N, M, x1, y1, x2, y2);
memset0(cnt);
memset0(cnt2);//由于都是采用递增方式赋值 因而都需要清零
}
}
EOF