1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| #include "iostream" #include "algorithm" #include "cstring" #include "cstdio" #include "cmath" #include "vector" #include "map" #include "set" #include "queue" using namespace std; #define MAXN 100006 #define int long long #define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i) #define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i) #define pii pair<int,int> #define fi first #define se second #define mp make_pair #define pb push_back #define eb emplace_back #define vi vector<int> #define all(x) (x).begin() , (x).end() #define mem( a ) memset( a , 0 , sizeof a ) typedef long long ll; int n , q , blo , bel[MAXN]; ll S[MAXN];
struct poi { int x , y; poi( ) { x = y = 0; } poi( int a , int b ) : x(a) , y(b) {} } A[MAXN] , B[MAXN] ;
ll gcd( ll a , ll b ) { return !b ? a : gcd( b , a % b ); }
struct frac { ll x , y; frac( ) : x(0) , y(0) {} frac( ll a , ll b ) : x(a) , y(b) { if( y < 0 ) x = -x , y = -y; } bool operator < ( const frac a ) const { return !y || x * a.y < y * a.x; } void ot( ) { ll g = gcd( abs( x ) , abs( y ) ); printf("%lld/%lld\n",x / g,y / g); } };
frac pr[61][MAXN] , su[61][MAXN];
int que[MAXN] , hd , tl; frac brul( int l , int r , int t = 0 , frac *as = nullptr , int kk = 0 ) { frac mx; if( !kk ) hd = 0 , tl = -1; rep( i , l , r ) { while( hd < tl && frac( B[que[hd]].y - A[i].y , B[que[hd]].x - A[i].x ) < frac( B[que[hd + 1]].y - A[i].y , B[que[hd + 1]].x - A[i].x ) ) ++ hd; if( hd <= tl ) mx = max( mx , frac( B[que[hd]].y - A[i].y , B[que[hd]].x - A[i].x ) ); while( hd < tl && frac( B[que[tl]].y - B[i].y , B[que[tl]].x - B[i].x ) < frac( B[que[tl - 1]].y - B[i].y , B[que[tl - 1]].x - B[i].x ) ) -- tl; que[++ tl] = i; if( t ) as[i] = mx; } return mx; } frac brur( int l , int r , int t = 0 , frac *as = nullptr ) { frac mx; hd = 0 , tl = -1; que[++ tl] = r; per( i , r - 1 , l ) { while( hd < tl && frac( A[que[hd]].y - B[i].y , A[que[hd]].x - B[i].x ) < frac( A[que[hd + 1]].y - B[i].y , A[que[hd + 1]].x - B[i].x ) ) ++ hd; mx = max( mx , frac( A[que[hd]].y - B[i].y , A[que[hd]].x - B[i].x ) ); while( hd < tl && frac( A[que[tl]].y - A[i].y , A[que[tl]].x - A[i].x ) < frac( A[que[tl - 1]].y - A[i].y , A[que[tl - 1]].x - A[i].x ) ) -- tl; que[++ tl] = i; if( t ) as[i] = mx; } return mx; }
void solve() { cin >> n >> q; blo = 1700; rep( i , 1 , n ) scanf("%lld",S + i) , S[i] += S[i - 1] , A[i] = poi( i , S[i] ) , B[i] = poi( i , S[i - 1] );
rep( i , 1 , n ) bel[i] = ( i - 1 ) / blo + 1; for( int i = 1 ; i <= n ; i += blo ) { brul( i , n , 1 , pr[bel[i]] ); brur( 1 , bel[i] * blo , 1 , su[bel[i]] ); } rep( i , 1 , q ) { int l , r; scanf("%lld%lld",&l,&r); if( bel[l] == bel[r] ) brul( l , r ).ot( ); else { frac mx; mx = brul( l , bel[l] * blo ); mx = max( mx , brul( ( bel[r] - 1 ) * blo + 1 , r , 0 , nullptr , 1 ) ); if( bel[l] + 1 < bel[r] ) mx = max( mx , max( pr[bel[l] + 1][r] , su[bel[r] - 1][l] ) ); mx.ot( ); } } }
signed main() { freopen("profit.in","r",stdin); freopen("profit.out","w",stdout);
solve(); }
|