CF535E Tavas and Pashmaks
阿新 • • 發佈:2018-11-10
連結CF535E Tavas and Pashmaks
- 給定二元組\((a,b)\),對於每一個\((a,b)\)詢問是否存在\((A,B)\),使得\(\frac {A}{a}+\frac {B}{b}\)在所有元素中最小,\(a,b\)實數,\(n\leq10^5\)
- 首先\(A,B\)的具體取值是沒有要求的,我們只關心\(\frac {A}{B}\)。
- 化簡一下,有\[z=\frac {\frac {A}{B}}{a_i}+ \frac {1}{b_i}\]
- 令\(\frac {A}{B}=x\),有\[y=\frac {x}{a_i} + \frac {1}{b_i}\]
- 所以問題轉化成,給出\(n\)條直線,詢問是否存在一個\(x\)使得對應直線\(y\)取值最小。
- 維護一個下凸殼即可。
- 注意這個斜率不能直接求,精度會炸裂,要這樣:
\[k=\frac {\frac {1}{b_j}-\frac {1}{b_i}}{\frac {1}{a_i}-\frac {1}{a_j}}\]
\[=\frac {a_i*a_j*(b_i-b_j)}{b_i*b_j*(a_j-a_i)}\] - 這樣的精度就會好一點。
#include<bits/stdc++.h> #define R register int #define ll long long #define db long double using namespace std; const int N=500001; int n,tot,len,tp,ans[N]; vector<int>G[N]; struct Qs{int u,v,id;}w[N],Q[N],STK[N]; int cmp(const Qs &x,const Qs &y){ if(x.u==y.u)return x.v>y.v; return x.u<y.u; } int gi(){ R x=0,k=1;char c=getchar(); while((c<'0'||c>'9')&&c!='-')c=getchar(); if(c=='-')k=-1,c=getchar(); while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar(); return x*k; } db sol(Qs x,Qs y){ db fz=(db)x.u*y.u*(x.v-y.v); db fm=(db)x.v*y.v*(y.u-x.u); return fz/fm; } int main(){ freopen("slay.in","r",stdin); freopen("slay.out","w",stdout); n=gi(); for(R i=1;i<=n;++i)w[i]=(Qs){gi(),gi(),i}; sort(w+1,w+n+1,cmp); for(R i=1,j=1;i<=n;i=j=j+1){ while(j<n&&w[j+1].u==w[i].u)++j; Q[++tot]=(Qs){w[i].u,w[i].v,tot}; for(R k=i;k<=j&&w[k].v==w[i].v;++k)G[tot].push_back(w[k].id); } for(R i=1;i<=tot;++i){ while(tp>1&&sol(STK[tp],STK[tp-1])>sol(Q[i],STK[tp-1]))--tp; STK[++tp]=Q[i]; } for (R i=1;i<=tp;++i) if (i==tp||sol(STK[i],STK[i+1])>0){ R x=STK[i].id; for(R i=0,sz=G[x].size();i<sz;++i) ans[++len]=G[x][i]; } sort(ans+1,ans+len+1); for(R i=1;i<=len;++i)printf("%d ",ans[i]); return 0; }