• [HNOI2012][BZOJ2732] 射箭 [二分+半平面交]


    题面

    BZOJ题面

    思路

    半平面交代码讲解戳这里,用的就是这道题

    我们射箭的函数形如$y=Ax^2+Bx$

    考虑每一个靶子$(x_0,y_1,y_2)$,实际上是关于$A,B$的不等式限制条件

    我们只要求出有没有$(A,B)$满足所有$2*n$个限制条件就可以了

    考虑一个限制条件$y_1leq Ax_0^2+Bx_0leq y_2$

    把一个$x_0$除过去,可以得到$B$关于$A$的半平面两个:

    $Bgeq -x_0A+frac{y_1}{x_0}$

    $Bleq -x_0A+frac{y_2}{x_0}$

    实际上就是两条平行线(不过这个性质没什么用)

    显然题目具有二分性,二分答案,每次对于前一部分的所有限制做半平面交即可

    技巧

    可以先把所有半平面(包括四个外围限制)排个序,然后每次二分求解的时候扫一遍提取出本次求解需要的

    半平面交如果可以剩下一个点(本题是可以的),需要在判断点是否在线的右边的函数里面修改条件,不能包括点在线上的情况

    半平面交模板参考这道题:所有线段有向,从a到b,半平面交求所有有向线段的左边半平面的交,外围框子是逆时针的

    同一份半平面交里面的所有点线关系都是一致的(都是左边or右边)

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cassert>
    #include<cmath>
    #define eps 1e-18
    #define inf 1e33
    #define ll long long
    using namespace std;
    inline int read(){
    	int re=0,flag=1;char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-') flag=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    	return re*flag;
    }
    inline bool sign(long double x){
    	if(x>eps) return 1;
    	if(x<-eps) return -1;
    	return 0;
    }
    int n,m;
    struct node{
    	long double x,y;
    	node(long double xx=0.0,long double yy=0.0){x=xx;y=yy;}
    	inline friend node operator +(const node &a,const node &b){return node(a.x+b.x,a.y+b.y);}
    	inline friend node operator -(const node &a,const node &b){return node(a.x-b.x,a.y-b.y);}
    	inline friend node operator *(const node &a,const long double &b){return node(a.x*b,a.y*b);}
    	inline friend long double operator *(const node &a,const node &b){return a.x*b.y-a.y*b.x;}
    	inline friend long double operator /(const node &a,const node &b){return a.x*b.x+a.y*b.y;}
    	inline friend long double slope(const node &a,const node &b){return atan2l(a.y-b.y,a.x-b.x);}
    }rt[300010];
    struct seg{
    	node a,b;long double k;int id;
    	seg(node aa=node(),node bb=node()){a=aa;b=bb;k=slope(aa,bb);id=0;}
    	seg(node aa,node bb,long double kk){a=aa;b=bb;k=kk;id=0;}
    	inline friend bool operator <(const seg &a,const seg &b){return a.k<b.k;}
    	inline friend node cross(const seg &a,const seg &b){
    		long double v1=(a.a-b.b)*(a.b-b.b);
    		long double v2=(a.a-b.a)*(a.b-b.a);
    		return b.b+(b.a-b.b)*(v1/(v1-v2));
    	}
    	inline friend bool right(const node &a,const seg &b){
    		return ((a-b.b)*(a-b.a))>eps;
    	}
    }lis[300010],a[300010],q[300010];
    inline bool solve(int lim){
    	int i,head=1,tail=0,flag,tot=0;
    	for(i=1;i<=m;i++) if(lis[i].id<=lim) a[++tot]=lis[i];
    	for(i=1;i<=tot;i++){
    		flag=0;
    		while((head<=tail)&&(!sign(a[i].k-q[tail].k))){
    			if(right(q[tail].a,a[i])) tail--;
    			else{flag=1;break;}
    		}
    		if(flag) continue;
    		while(head<tail&&right(rt[tail],a[i])) tail--;
    		while(head<tail&&right(rt[head+1],a[i])) head++;
    		q[++tail]=a[i];
    		if(head<tail) rt[tail]=cross(q[tail],q[tail-1]);
    	}
    	while(head<tail&&right(rt[tail],q[head])) tail--;
    	while(head<tail&&right(rt[head+1],q[tail])) head++;
    	return (tail-head>1);
    }
    const long double pi=acos(-1.0);
    int main(){
    	n=read();int i;long double x1,y1,y2;
    	m=n<<1;
    	for(i=1;i<=n;i++){
    		x1=read();y1=read();y2=read();
    		lis[i]=seg(node(0,y1/x1),node(1,y1/x1-x1));
    		lis[i+n]=seg(node(1,y2/x1-x1),node(0,y2/x1));
    		lis[i].id=lis[i+n].id=i;
    	}
    	lis[++m]=seg(node(-1e12,1e12),node(-1e12,-1e12),pi/2.0);
    	lis[++m]=seg(node(1e12,1e12),node(-1e12,1e12),0);
    	lis[++m]=seg(node(1e12,-1e12),node(1e12,1e12),-pi/2.0);
    	lis[++m]=seg(node(-1e12,-1e12),node(1e12,-1e12),pi);
    	sort(lis+1,lis+m+1);
    	int l=1,r=n,mid;
    	while(l<r){
    		mid=(l+r)>>1;mid++;
    		if(solve(mid)) l=mid;
    		else r=mid-1;
    	}
    	cout<<l<<'
    ';
    }
    
  • 相关阅读:
    .NET5 ABP框架(二)- WebApi
    找不到版本为(>=2.0.3)的包NETStandard.Library -在 Microsoft Visual Stduio Offine Packages 中找到2个版本[ 最接近:1.6.1 ]
    .NET5 ABP框架(一)
    开学第一节课
    开学考试
    参考:
    安装git
    org.apache.thrift.transport.TTransportException: Could not create ServerSocket on address 0.0.0.0/0.0.0.0:9083.
    hive insert 出现问题
    hive开启远程连接方法
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/10662935.html
Copyright © 2020-2023  润新知