1. 程式人生 > 實用技巧 >[20200727NOIP提高組模擬T3]計算幾何

[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('\n');}