#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 ll inf = (1<<30); // O(N) auto f = [=](ll x) { if (x <= 0) return inf; ll maxF = a[0]+b[0]*x; ll 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; ll left = 1; ll right = (1<<30); // O(N*1000) for (int loop = 0; loop < maxLoop; ++loop) { if ( left == right ) break; // // l ---u---v--- r // ll u = (left*2 + right)/3; ll v = (left + right*2)/3; if ( f(u) > f(v) ) left = u; else right = v; } ll x = (left+right)/2; // 前後 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