#include typedef long long ll; typedef unsigned long long ull; #define FOR(i,a,b) for(int (i)=(a);i<(b);i++) #define REP(i,n) FOR(i,0,n) #define RANGE(vec) (vec).begin(),(vec).end() using namespace std; class BeautifulWhitespace2 { public: void solve(void) { int N; cin>>N; vector a(N); vector b(N); REP(i,N) cin>>a[i]>>b[i]; // // // / | // --- / | // --- / | // // のような傾きの異なる 3 直線とすると // max(a[i]+b[i]*x) は領域 A 側にもっとも近い線分 // min(a[i]+b[i]*x) は領域 B 側にもっとも近い線分 // // |/ // A / // /| // /|------- // ----/- // / | B // // によって構成される。また max(...) => min(...) なので // 差は必ず 0 以上となる。よって f(x) は極値を 1 つもつ凹関数となる。 // 三分探索をすればよい。 const double inf = (1<<30); // O(N) auto f = [=](double x) { if (x <= 0) return inf; double maxF = a[0]+b[0]*x; double minF = a[0]+b[0]*x; FOR(i,1,N) { minF = min(minF, a[i]+b[i]*x); maxF = max(maxF, a[i]+b[i]*x); } return maxF - minF; }; const int maxLoop = 1000; double left = 1; double right = (1<<30); // O(N*1000) for (int loop = 0; loop < maxLoop; ++loop) { if ( fabs(left - right) < 1e-3 ) break; // // l ---u---v--- r // double u = (left*2 + right)/3; double v = (left + right*2)/3; if ( f(u) > f(v) ) left = u; else right = v; } ll x = (left+right)*0.5; // 前後 1 つ分くらいは調べてみる auto xs = vector {x-1, x, x+1}; cout<<*min_element(RANGE(xs), [=](ll a, ll b) { return f(a)solve(); delete obj; return 0; } #endif