[+巧み半分ANSWERを変換AGC040D

そこ\(N- \)ストリップ長さ\(1 \)バランスビームの、そして小さなP Qは、小さな遊びのバランスビームを使用することを目的と

小さなPを過ごすことが知られて\(a_iを\)秒セクションを終える\(I \)条のバランスビームを、小さなQかかります\(B_i \)秒セクションを終える\(I \)セクションビームを。彼らは長い間、バランスビームを埋め合わせ過ごすことになります\(N \)歩き始めたバランスビームの、そして小さなPは小さなQは、バランスビーム上の点を選ぶだろう、最初から行くを開始します。

リトルPは勝つことができると最後に小さなQは、小さなPが追い抜いた場合にのみ小さなQ.もし

リトルPは今彼女が優勝最大化させ、順番を思い付くしたいです。あなたは、この最大の勝率、最も簡単な分数形式で解答出力を誘います。


フィールは、小さなPの勝利ポイントを作る立場に見つけることができます] [接頭辞です

次にことができる\(Xは\)の距離を移動軸\(Y \)は、システムが小さなPを描画するために、移動時間のために確立され、Qは小さな折り目を移動その一部の交差点[] []を有することになる直交座標平面の軸線

その後、ちょうど彼らが見つけることができると感じ、小さな折れ線Pと破線Q小さな下降レベルは一つだけ交点、ラインと小Qである\(xは\)横軸との交点を軸線Pの小さなセクションを獲得することができています右端点[]

設けられた小小P Qは、折り線の交差の(翻訳後)\((X0、Y0)\ ) 後、新しいポリラインを考え出すこと\(C \) 満たす\(X0 \)前のすべての行を折る(\ B \)で、傾きである\(X0 \)へのすべての後のポリライン)は\(\の傾きである[このアイデアは、OWOをテストするために、素晴らしいです]

明らかに\(C \)は、エンドポイントがなければなりませんである(\)(N、S \ ;(S = \和\ limits_ {I = 1} ^ N a_iを)\) []

だから、作るために\(C \) 横軸の最大は、[直線の傾きの選挙が比較的大きいことを、できるだけわずかな直線を選択する必要があります]

次に、あなたがまっすぐに知ることができます\(I \)への貢献\(MAX(a_iを、b_iを)\)貢献するこの方法を達成することにある(a_iを<b_i \)\リリースリニア(X_0 \)\置くために他の、左側に\ (X0 \)の右側の[]

次に練習音楽はより明確である:最初の直線で\(MAX(a_iを、b_i) \) を降順にソートし、次に列挙する\(C \)をし、\(X \)であり、シャフトの直線の交点に、セット\(K \)次に、行数の半分が選択され、満足しなければならない\(\和\ limits_ {iは ^ {中間マックス= 1}は(a_iを、b_i)+ b_k \ GEQ S、\和\ limits_ ^ {中間{iが1 =} } MAX(a_iを、b_i)は<S \) ] [正当です

そして、あなたは] [それは日当何で音楽分子[]特別な契約の小数部分の喜びの整数部分を計算することができます

#include <bits/stdc++.h>
#define N 100005
#define ll long long
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define pll pair<ll,ll>
#define fr first
#define sd second
using namespace std;

pll a[N];
ll ansx=0,ansy=1,sum[N],S=0;
bool cmp(const pll &a,const pll &b){ return a.fr>b.fr; }
ll calc(int x,int y){ return y<=x?sum[x]-a[y].fr:sum[x]; }
ll gcd(ll x,ll y){ return x%y?gcd(y,x%y):y; }

int main(){
    int n; scanf("%d",&n);
    For(i,1,n){
        scanf("%lld%lld",&a[i].fr,&a[i].sd);
        S+=a[i].fr;
        a[i].fr=max(a[i].fr,a[i].sd);
    }
    sort(a+1,a+n+1,cmp);
    For(i,1,n) sum[i]=sum[i-1]+a[i].fr;
    For(i,1,n){
        int l=0,r=n,num=-1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(calc(mid,i)>=S-a[i].sd) num=mid,r=mid-1;
            else l=mid+1;
        }
        if(num<0) continue;
        if(calc(num,i)>=S) continue;
        ll nowx=1ll*(1ll*n-(num-(i<=num)))*a[i].sd-S+calc(num,i),nowy=1ll*n*a[i].sd;
        ll p=gcd(nowx,nowy);nowx/=p,nowy/=p;
        if(1.0*nowx*ansy>1.0*nowy*ansx) ansx=nowx,ansy=nowy;        
    }
    printf("%lld %lld\n",ansx,ansy);
}

おすすめ

転載: www.cnblogs.com/PsychicBoom/p/11938984.html