TOYS
题目链接
题意:
有一个矩形盒子,放入n块按照x轴排序的不相交的隔板,这样就将矩形盒子分成了n+1块区域。现在将m个玩具放入这个矩形盒子,统计每个区域的玩具个数。
思路:
利用叉乘的性质判断在当前隔板的左边还是右边,由于每个玩具在隔板的左边或右边具有单调性,所以可以二分优化
ac代码:
枚举+二分O(mlogn)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;
// `计算几何模板`
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//`Compares a double to zero`
int sgn(double x){
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
//square of a double
inline double sqr(double x){return x*x;}
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){
x = _x;
y = _y;
}
void input(){
scanf("%lf%lf",&x,&y);
}
void output(){
printf("%.2f %.2f\n",x,y);
}
bool operator == (Point b)const{
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const{
return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
//叉积
double operator ^(const Point &b)const{
return x*b.y - y*b.x;
}
//点积
double operator *(const Point &b)const{
return x*b.x + y*b.y;
}
//返回长度
double len(){
return hypot(x,y);//库函数
}
//返回长度的平方
double len2(){
return x*x + y*y;
}
//返回两点的距离
double distance(Point p){
return hypot(x-p.x,y-p.y);
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator *(const double &k)const{
return Point(x*k,y*k);
}
Point operator /(const double &k)const{
return Point(x/k,y/k);
}
//`计算pa 和 pb 的夹角`
//`就是求这个点看a,b 所成的夹角`
//`测试 LightOJ1203`
double rad(Point a,Point b){
Point p = *this;
return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
}
//`化为长度为r的向量`
Point trunc(double r){
double l = len();
if(!sgn(l))return *this;
r /= l;
return Point(x*r,y*r);
}
//`逆时针旋转90度`
Point rotleft(){
return Point(-y,x);
}
//`顺时针旋转90度`
Point rotright(){
return Point(y,-x);
}
//`绕着p点逆时针旋转angle`
Point rotate(Point p,double angle){
Point v = (*this) - p;
double c = cos(angle), s = sin(angle);
return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
}
};
const int N = 5010;
Point U[N], L[N];
int cnt[N];
bool check(Point a, Point b) {
return sgn(a ^ b) == 1;
}
int main() {
int n, m, x1, y1, x2, y2;
while (scanf("%d", &n), n) {
memset(cnt, 0, sizeof cnt);
scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
for (int i = 1; i <= n; ++ i) {
int a, b;
scanf("%d %d", &a, &b);
U[i] = Point(a, y1), L[i] = Point(b, y2);
}
U[n + 1] = Point(x2, y1), L[n + 1] = Point(x2, y2);
for (int i = 1; i <= m; ++ i) {
int x, y;
scanf("%d %d", &x, &y);
int l = 1, r = n + 1, mid, ans;
while (l <= r) {
mid = l + r >> 1;
if (check(U[mid] - L[mid], Point(x, y) - L[mid]))
ans = mid, r = mid - 1;
else l = mid + 1;
}
cnt[ans - 1] ++ ;
}
for (int i = 1; i <= n + 1; ++ i) {
printf("%d: %d\n", i - 1, cnt[i - 1]);
}
printf("\n");
}
return 0;
}
暴力枚举O(n*m)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;
// `计算几何模板`
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//`Compares a double to zero`
int sgn(double x){
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
//square of a double
inline double sqr(double x){return x*x;}
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){
x = _x;
y = _y;
}
void input(){
scanf("%lf%lf",&x,&y);
}
void output(){
printf("%.2f %.2f\n",x,y);
}
bool operator == (Point b)const{
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const{
return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
//叉积
double operator ^(const Point &b)const{
return x*b.y - y*b.x;
}
//点积
double operator *(const Point &b)const{
return x*b.x + y*b.y;
}
//返回长度
double len(){
return hypot(x,y);//库函数
}
//返回长度的平方
double len2(){
return x*x + y*y;
}
//返回两点的距离
double distance(Point p){
return hypot(x-p.x,y-p.y);
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator *(const double &k)const{
return Point(x*k,y*k);
}
Point operator /(const double &k)const{
return Point(x/k,y/k);
}
//`计算pa 和 pb 的夹角`
//`就是求这个点看a,b 所成的夹角`
//`测试 LightOJ1203`
double rad(Point a,Point b){
Point p = *this;
return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
}
//`化为长度为r的向量`
Point trunc(double r){
double l = len();
if(!sgn(l))return *this;
r /= l;
return Point(x*r,y*r);
}
//`逆时针旋转90度`
Point rotleft(){
return Point(-y,x);
}
//`顺时针旋转90度`
Point rotright(){
return Point(y,-x);
}
//`绕着p点逆时针旋转angle`
Point rotate(Point p,double angle){
Point v = (*this) - p;
double c = cos(angle), s = sin(angle);
return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
}
};
const int N = 5010;
Point U[N], L[N];
int cnt[N];
int main() {
int n, m, x1, y1, x2, y2;
while (scanf("%d", &n), n) {
memset(cnt, 0, sizeof cnt);
scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
for (int i = 1; i <= n; ++ i) {
int a, b;
scanf("%d %d", &a, &b);
U[i] = Point(a, y1), L[i] = Point(b, y2);
}
for (int i = 1; i <= m; ++ i) {
int x, y;
scanf("%d %d", &x, &y);
int j = 1;
for (; j <= n; ++ j) {
//U[j].output(), L[j].output();
if (sgn((U[j] - L[j]) ^ (Point(x, y) - L[j])) == 1) {
break;
}
}
// cout << j << " ";
// cout << endl;
cnt[j - 1] ++ ;
}
for (int i = 1; i <= n + 1; ++ i) {
printf("%d: %d\n", i - 1, cnt[i - 1]);
}
printf("\n");
}
return 0;
}
Toy Storage
题意同上
区别这题直线未排序
排序+二分
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;
// `计算几何模板`
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//`Compares a double to zero`
int sgn(double x){
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
//square of a double
inline double sqr(double x){return x*x;}
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){
x = _x;
y = _y;
}
void input(){
scanf("%lf%lf",&x,&y);
}
void output(){
printf("%.2f %.2f\n",x,y);
}
bool operator == (Point b)const{
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const{
return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
//叉积
double operator ^(const Point &b)const{
return x*b.y - y*b.x;
}
//点积
double operator *(const Point &b)const{
return x*b.x + y*b.y;
}
//返回长度
double len(){
return hypot(x,y);//库函数
}
//返回长度的平方
double len2(){
return x*x + y*y;
}
//返回两点的距离
double distance(Point p){
return hypot(x-p.x,y-p.y);
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator *(const double &k)const{
return Point(x*k,y*k);
}
Point operator /(const double &k)const{
return Point(x/k,y/k);
}
//`计算pa 和 pb 的夹角`
//`就是求这个点看a,b 所成的夹角`
//`测试 LightOJ1203`
double rad(Point a,Point b){
Point p = *this;
return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
}
//`化为长度为r的向量`
Point trunc(double r){
double l = len();
if(!sgn(l))return *this;
r /= l;
return Point(x*r,y*r);
}
//`逆时针旋转90度`
Point rotleft(){
return Point(-y,x);
}
//`顺时针旋转90度`
Point rotright(){
return Point(y,-x);
}
//`绕着p点逆时针旋转angle`
Point rotate(Point p,double angle){
Point v = (*this) - p;
double c = cos(angle), s = sin(angle);
return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
}
};
struct Line{
Point l, u;
// Line(){}
// Line(Point _x,Point _y){
// l = _x;
// u = _y;
// }
bool operator < (Line b) const{
if (l == b.l) return u < b.u;
return l < b.l;
}
};
const int N = 5010;
Point U[N], L[N];
int cnt[N], qcnt[N];
Line LU[N];
bool check(Point a, Point b) {
return sgn(a ^ b) == 1;
}
int main() {
int n, m, x1, y1, x2, y2;
while (scanf("%d", &n), n) {
memset(cnt, 0, sizeof cnt);
memset(qcnt, 0, sizeof qcnt);
scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
for (int i = 1; i <= n; ++ i) {
int a, b;
scanf("%d %d", &a, &b);
U[i] = Point(a, y1), L[i] = Point(b, y2);
LU[i - 1] = {L[i], U[i]};
}
U[n + 1] = Point(x2, y1), L[n + 1] = Point(x2, y2);
LU[n] = {L[n + 1], U[n + 1]};
sort(LU, LU + n);
// for (int i = 0; i <= n; ++ i) {
// LU[i].l.output(), LU[i].u.output();
// }
// for (int i = 1; i <= m; ++ i) {
// int x, y;
// scanf("%d %d", &x, &y);
// }
//for (int i = 0; i <= n; ++ i) LU[i].l.output(), LU[i].u.output();
for (int i = 1; i <= m; ++ i) {
int x, y;
scanf("%d %d", &x, &y);
int l = 0, r = n, mid, ans;
while (l <= r) {
mid = l + r >> 1;
Point a = LU[mid].u, b = LU[mid].l;
if (check(a - b, Point(x, y) - b))
//if (check(LU[mid].u - LU[mid].l, Point(x, y) - LU[mid]).l))
ans = mid, r = mid - 1;
else l = mid + 1;
}
//cout << ans << endl;
cnt[ans] ++ ;
}
for (int i = 0; i <= n; ++ i) {
qcnt[cnt[i]] ++ ;
//printf("%d: %d\n", i, cnt[i]);
}
printf("Box\n");
for (int i = 1; i <= m; ++ i) {
if (qcnt[i])
printf("%d: %d\n", i, qcnt[i]);
}
//printf("\n");
}
return 0;
}
枚举暴力
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;
// `计算几何模板`
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//`Compares a double to zero`
int sgn(double x){
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
//square of a double
inline double sqr(double x){return x*x;}
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){
x = _x;
y = _y;
}
void input(){
scanf("%lf%lf",&x,&y);
}
void output(){
printf("%.2f %.2f\n",x,y);
}
bool operator == (Point b)const{
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const{
return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
//叉积
double operator ^(const Point &b)const{
return x*b.y - y*b.x;
}
//点积
double operator *(const Point &b)const{
return x*b.x + y*b.y;
}
//返回长度
double len(){
return hypot(x,y);//库函数
}
//返回长度的平方
double len2(){
return x*x + y*y;
}
//返回两点的距离
double distance(Point p){
return hypot(x-p.x,y-p.y);
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator *(const double &k)const{
return Point(x*k,y*k);
}
Point operator /(const double &k)const{
return Point(x/k,y/k);
}
//`计算pa 和 pb 的夹角`
//`就是求这个点看a,b 所成的夹角`
//`测试 LightOJ1203`
double rad(Point a,Point b){
Point p = *this;
return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
}
//`化为长度为r的向量`
Point trunc(double r){
double l = len();
if(!sgn(l))return *this;
r /= l;
return Point(x*r,y*r);
}
//`逆时针旋转90度`
Point rotleft(){
return Point(-y,x);
}
//`顺时针旋转90度`
Point rotright(){
return Point(y,-x);
}
//`绕着p点逆时针旋转angle`
Point rotate(Point p,double angle){
Point v = (*this) - p;
double c = cos(angle), s = sin(angle);
return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
}
};
const int N = 5010;
Point U[N], L[N];
int cnt[N], qcnt[N];
int main() {
int n, m, x1, y1, x2, y2;
while (scanf("%d", &n), n) {
memset(cnt, 0, sizeof cnt);
memset(qcnt, 0, sizeof qcnt);
scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
for (int i = 1; i <= n; ++ i) {
int a, b;
scanf("%d %d", &a, &b);
U[i] = Point(a, y1), L[i] = Point(b, y2);
}
U[n + 1] = Point(x2, y1), L[n + 1] = Point(x2, y2);
for (int i = 1; i <= m; ++ i) {
int x, y;
scanf("%d %d", &x, &y);
int j = 1, ans;
double minn = inf;
for (; j <= n + 1; ++ j) {
if (sgn((U[j] - L[j]) ^ (Point(x, y) - L[j])) == 1
&& sgn(minn - L[j].x) == 1) {
ans = j;
minn = L[j].x;
}
}
// cout << ans << "\n";
// cout << minn << " ";
// cout << endl;
cnt[ans - 1] ++ ;
}
for (int i = 1; i <= n + 1; ++ i) {
qcnt[cnt[i - 1]] ++ ;
//printf("%d: %d\n", i - 1, cnt[i - 1]);
}
printf("Box\n");
for (int i = 1; i <= m; ++ i) {
if (qcnt[i])
printf("%d: %d\n", i, qcnt[i]);
}
//printf("\n");
}
return 0;
}