【GMOJ6800】模擬spongebob
阿新 • • 發佈:2020-10-16
題目
題目連結:https://gmoj.net/senior/#main/show/6800
給出 \(n\) 和兩個長度為 \(n\) 的陣列 \(a,b\),求
其中 \(x\in \mathbb{R}\)。
思路
先把 \(a=0\) 的所有直線的 \(|b|\) 加到答案裡。
對於剩餘的直線,我們按照他們與 \(x\) 軸交點排序,依次列舉交點區間並計算出此時最優的 \(x\),判斷 \(x\) 與當前區間位置分別計算答案即可。
時間複雜度 \(O(n\log n)\)。
程式碼
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=300010; int n,m; ll sum,suma,sumb; double ans; struct node { ll a,b; double p; }a[N]; bool cmp(node x,node y) { if (x.a==0) return 0; if (y.a==0) return 1; return x.p<y.p; } int main() { freopen("spongebob.in","r",stdin); freopen("spongebob.out","w",stdout); scanf("%d",&m); n=m; for (int i=1;i<=m;i++) { scanf("%lld%lld",&a[i].a,&a[i].b); if (a[i].a!=0) a[i].p=-1.0*a[i].b/a[i].a; else sum+=abs(a[i].b),n--; } sort(a+1,a+1+m,cmp); for (int i=1;i<=n;i++) if (a[i].a>0) suma-=a[i].a,sumb-=a[i].b; else suma+=a[i].a,sumb+=a[i].b; a[0].p=-10000000000000000.0; a[n+1].p=10000000000000000.0; ans=10000000000000000.0; for (int i=1;i<=n+1;i++) { double l=a[i-1].p,r=a[i].p,x=-1.0*sumb/suma; if (l<=x && x<=r) ans=0; if (x<l) ans=min(ans,suma*l+sumb); if (x>r) ans=min(ans,suma*r+sumb); if (a[i].a>0) suma+=2LL*a[i].a,sumb+=2LL*a[i].b; else suma-=2LL*a[i].a,sumb-=2LL*a[i].b; } printf("%.8lf",ans+sum); return 0; }