HZOJ 导弹袭击

比较显然的一个性质是如果存在$a(i)>=a(j) \& \& b(i)>=b(j)$那么j没用。

我们并不需要A,B的具体取值,我们之关心$\frac {A}{B}$。

不妨令B=1,x=A,那么$t=\frac {x}{a} + \frac {1}{b}$。

那么问题转化为:是否存在一个x使i的t最小。

显然是一个上凸包,用单调栈维护即可。

关于单调栈维护凸包可以看这篇博客

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define int LL
#define pair pair<int,int>
#define MP(a,b) make_pair(a,b)
#define LL long long
using namespace std;
const long double eps=0;
struct node
{
	LL a,b,id,is;
	#define a(i) A[i].a
	#define b(i) A[i].b
	#define id(i) A[i].id
	#define is(i) A[i].is
	long double xl(){return 1.0/a;}
	long double jj(){return 1.0/b;}
	friend bool operator < (node a,node b)
	{return a.a==b.a?a.b<b.b:a.a>b.a;}
}A[500010],B[500010];
bool cmp1(node a,node b){return a.a==b.a?a.b<b.b:a.a<b.a;}
bool cmp2(node a,node b){return a.b==b.b?a.a<b.a:a.b<b.b;}
bool cmp3(node a,node b){return a.a<b.a;}
//long double get(node a,node b){return (long double)(1.0/b.b-1.0/a.b)/(1.0/a.a-1.0/b.a);}
long double get(node a,node b){return (long double)(1.0*(a.b-b.b)*a.a*b.a)/(1.0*(b.a-a.a)*a.b*b.b);}
int n;bool al[510000];
map<pair,bool>mp;
map<LL,int>ca;
int sta[510000],top;
#define ST sta[top]
signed main()
{
//	freopen("slay2.in","r",stdin);
//	freopen("1.out","w",stdout);
	
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a(i)>>b(i),id(i)=i,B[i]=A[i],is(i)=1;
	
	sort(A+1,A+n+1,cmp1);int maxb=b(n);
	for(int i=n-1;i;i--)
	{
		if(maxb>=b(i))is(i)=0;
		maxb=max(maxb,b(i));
	}

	sort(A+1,A+n+1);
	for(int i=1;i<=n;i++)
	if(is(i))
	{	
		while(top>1&&get(A[i],A[sta[top-1]])-get(A[ST],A[sta[top-1]])>eps)top--;	
		if(top<=1|| (get(A[i],A[ST])>0)  )sta[++top]=i;
	}
	for(int i=1;i<=top;i++)mp[MP(a(sta[i]),b(sta[i]))]=1;
	for(int i=1;i<=n;i++)if(mp[MP(B[i].a,B[i].b)])printf("%lld ",i);
}

猜你喜欢

转载自www.cnblogs.com/Al-Ca/p/11686525.html