题目大意:
给你若$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(' ');}