GYM-100520 B. Bayes' Law
阿新 • • 發佈:2018-11-11
題解:區間[L,R]得出的答案我們知道,它最多有一個端點的線段會被截斷。故二分的時候固定一個線段的端點就好了。然後列舉最右端的那條線段是否被分隔開。 然後固定右端點,分割左端點的線段。
#include<bits/stdc++.h> #define fuck(x) cout<<'['<<#x<<' '<<x<<']'<<endl using namespace std; const double eps = 1e-8; typedef long long ll; const int MX = 2e5+7; double cnt[MX],sum[MX],x[MX],y[MX]; int n,tail; double L,R,ans; int dcmp(double a) { if(fabs(a) < eps) return 0; return a < 0? -1 : 1; } double check(int id, double mid) { int k = lower_bound(cnt,cnt+tail,mid) - cnt; k = min(tail-1,k); double ret = sum[k] - sum[id]; if(k&1) ret -= max(0.0, cnt[k]-mid); //線段是1-0,3-2,5-4這樣的,所以必須是奇數才能減 return ret; } void update(int id, double mid, bool rev) { double l,r; if(rev){ r = x[n] - cnt[id]; l = x[n] - mid; } else{ l = cnt[id]; r = mid; } if(dcmp(r-l-ans) <= 0){ ans = r-l; L = l; R = r; } } void work(bool rev,double A) { for(int i = 0; i < tail; i += 2){ double l = cnt[i], r = x[n]+1; for(int j = 1; j <= 60; j++){ double mid = (l+r)*0.5; if(dcmp(check(i,mid)-A ) >= 0) r = mid; else l = mid; } if(l > x[n]+0.1) break; update(i,l,rev); } } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #else freopen("bayes.in", "r", stdin); freopen("bayes.out", "w", stdout); #endif // LOCAL double a,b,A; while(~scanf("%d",&n)){ if(n == 0) break; tail = 0; scanf("%lf%lf%lf",&a,&b,&A); for(int i = 0; i <= n; i++){ scanf("%lf%lf",&x[i],&y[i]); } for(int i = 1; i <= n; i++){ double dx = x[i] - x[i-1], dy = y[i] - y[i-1]; if(dcmp(dy) == 0 && a <= y[i] && y[i] <= b){ cnt[tail++] = x[i-1]; cnt[tail++] = x[i]; } else{ double t = dy/dx; double xl = x[i-1] + (t < 0? (b-y[i-1])/t : (a-y[i-1])/t); double xr = x[i] + (t < 0? (a-y[i])/t : (b-y[i])/t ); xl = max(xl,x[i-1]); xr = min(xr,x[i]); if(xl > xr) continue; cnt[tail++] = xl; cnt[tail++] = xr; } } double len = 0; for(int i = 1; i < tail; i+=2){ len += cnt[i] - cnt[i-1]; } A *= len; ans = x[n]; L = 0, R = 0; for(int i = 1; i < tail; i++){ if(i&1) sum[i] = sum[i-1] + cnt[i] - cnt[i-1]; else sum[i] = sum[i-1]; } work(0,A); for(int i = 0; i < tail; i++) cnt[i] = x[n] - cnt[i]; reverse(cnt,cnt+tail); for(int i = 1; i < tail; i++){ if(i&1) sum[i] = sum[i-1] + cnt[i] - cnt[i-1]; else sum[i] = sum[i-1]; } work(1,A); printf("%.12f %.12f\n",L,R); } return 0; }