[20200727NOIP提高组模拟T3]计算几何

题目大意:

  给你若$n$个在$x$轴上的不重合的点和$n$个在$y$轴上的不重合的点(均在坐标轴正半轴上),请你构造出$n$条互不相交的线段.现有$m$组询问,对于每组询问,给出一点$P(x,y)$,请你求出线段$OP$与你构造出的$n$条线段有多少交点.(点$P$在第一象限)

solution:

  首先我们不难想出构造方法,将$x$轴上点按从小到大排,$y$轴上点从小到大排,然后依次连接即可无交点.然后对于查询,显然具有单调性,$logn$查询即可.

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#define R register
#define next awawn
#define debug puts("mlg")
#define maxn 200010
using namespace std;
typedef long long ll;
typedef long double D;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writesp(ll x);
inline void writeln(ll x);
ll n,A[100010],B[100010];
struct node{
    ll a,b;
}seg[100010];
ll Q;
inline bool check(ll x,ll y,ll k){
    return (double)((D)seg[k].a*(D)seg[k].b/((D)seg[k].b*(D)x+(D)seg[k].a*(D)y))<=1;
}
int main(){
    n=read();
    for(R ll i=1;i<=n;i++) A[i]=read();
    for(R ll i=1;i<=n;i++) B[i]=read();
    sort(A+1,A+n+1);sort(B+1,B+n+1);
    for(R ll i=1;i<=n;i++) seg[i].a=A[i],seg[i].b=B[i];
    Q=read();
    while(Q--){
        ll x=read(),y=read();
        ll l=0,r=n;
        while(l+1<r){
            ll mid=l+r>>1;
            if(check(x,y,mid)) l=mid;
            else r=mid-1;
        }
        writeln(check(x,y,l+1)?l+1:l);        
    }    
}
inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x);putchar(' ');}
inline void writeln(ll x){write(x);putchar('
');}
原文地址:https://www.cnblogs.com/ylwtsq/p/13385207.html