2983. 玩具 _ 计算几何
题意
一个盒子被分成了若干个区域,有m个小球,问每个区域里分别有多少个小球。
数据保证玩具不会恰好落在纸板上,也不会落在盒子外。
思路
如何判断小球是否在一个区域内?
我们发现一个小球在区域x,也就是说所有编号小于x的所有隔板都在小球坐标的左边,所有编号大于x的隔板都在小球坐标的右边。
因此问题就变成了如何判断点在直线的左边或者右边.
而且显然满足二段性,因此我们可以二分求解。
如何判断点在直线的左边或者右边
模板公式,判断叉积正负即可。
代码
#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
#define x first
#define y second
using namespace std;
const int N = 5010;
int n,m;
pii a[N],b[N];
int ans[N];
int cross(int x1,int y1,int x2,int y2){
return x1*y2-x2*y1;
}
int area(pii a,pii b,pii c){
return cross(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
int find(int x,int y){
int l=0,r=n;
while(l<r){
int mid=(l+r)/2;
if(area(b[mid],a[mid],{x,y})>0) r=mid;
else l=mid+1;
}
return r;
}
void solve(){
bool is_first=true;
while(cin>>n && n){
int x1,y1,x2,y2;cin>>m>>x1>>y1>>x2>>y2;
for(int i=0;i<n;i++){
int u,l;cin>>u>>l;
a[i]={u,y1},b[i]={l,y2};
}
a[n]={x2,y1},b[n]={x2,y2};
if(is_first) is_first=false;
else puts(" ");
memset(ans, 0, sizeof ans);
for(int i=0;i<m;i++){
int x,y;cin>>x>>y;
ans[find(x,y)]++;
}
for(int i=0;i<=n;i++) cout<<i<<": "<<ans[i]<<endl;
}
}
signed main(){
int t=1;
// cin>>t;
while(t--)
solve();
return 0;
}