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); }
波澜前,面不惊。