LGOI P1314スマート品質監督

ここで、元のタイトルをスタンプ

タイトル説明

小T彼は鉱物の数の品質を検査するため、最近、責任の品質監督、です。これらの鉱物があり、\(N \)から番目鉱石\(1 \)\(N \)個々に番号を付け、それぞれの鉱物が自重有する\(w_i \)の値(V_Iを\)\ミネラル検査プロセスは、次のとおりです。

  1. 与えられメートルの間隔\(L_iを、R_iと\)

  2. パラメータを選択します\(W \)

  3. 間隔の\([L_iを、R_iを] \)この間隔鉱石チェック値を算出し、Y I

\ [Y_I =(\ sum_j 1)(\ sum_j {v_j})、\ [L_iを、R_iを】クワッドJ \ \クワッドw_j \ GEQ \ W]

これは、\(J \)鉱石の数です。

これらの鉱物の試験結果\(Y \)各セクションの値をテストすると。すなわち:\(Y_1 + ... + Y_2 Y_M \)

これらの試験結果やミネラルは、標準的な値を指定した場合、\(S \)あまり違い、あなたはミネラルの別のバッチをチェックしに行く必要があります。小T時間のかかる、彼はパラメータを調整したかったので、鉱物の別のグループをテストする必要はありません\(W \) 値をそのための標準的な値にできる近いな限りのテスト結果\(S \)に持っていても、(\ SY)\最小の絶対値。ヘルプには、最小値を見つけてください。

入力形式

最初の行は三つの整数含ま\(N、M \)を、各数値は標準値と鉱石部の数を表します。

\(N- \)行は、各列\(2 \)整数は、スペースで区切られた\(I + 1 \)ラインが表す(I \)\鉱石数の重量(\ W_i)を\そして、の値は\(V_I \)

\(M \)間隔を表す線、各行\(2 \)整数、スペースで区切られた中間体、\(I + N + 1 \ ) 間隔表す線\([L_iを、R_iを]を\ ) 2つのエンドポイント\(L_iを\)\(R_iと\) 注:異なる間隔は、一致または重複してもよいです。

出力フォーマット

最小値を示す整数が必要。

サンプル入力と出力

入力#1
。5 15 3
。1. 5
2. 5
。3. 5
。4. 5
。5. 5
。1. 5
2. 4
。3. 3
出力#1
10

説明/ヒント

例説明[O]

場合\(W \である)群から選択される\(4 \) 3つの試験間隔の値であった\(20,5,0 \) これらの鉱物の試験結果(\ 25 \) 次いで、標準的な値\(S \)異なる最小\(10 \)

[データ範囲]

ため\(10 \%\)データがある(1≤n、m≤10\)\

以下のために(30 \%\)\データの、ある\(1≤n、m≤500\。)

ため\(50 \%\)データがある(1≤n、m≤5,000\)\

ため\(70 \%\)データがある(1≤n、m≤10,000\)\

以下のために(100 \%\)\データの、ある(\ 1≤n、m≤200,000,0<w_i 、v_i≤10は^ 6,0 <S≤10^ {12}、1≤L_i≤R_iの≤n\



問題の解

これは、TLEの思考せず、明らかにハーフボードであります

私は、どの程度まで、このトピックの背景の発言は非常に奇妙なああです感じます

最初の関数を検討し\(Y(W_ {CURを} )\) 、直感が教えてくれる\(Y(W_ {} CUR )\) 単調です。書くのが面倒証明します。 実際に、私は書くつもりはありません

\ [Y(W_ {CUR})= \ sum_i ^ M((\ sum_j 1)(\ sum_j {V_I}))、\ [L_iを、R_iを】クワッドJ \ \クワッドw_j \ GEQ W_ {CUR} \ ]

次は、距離を見つけることである\(Y(W_ {CUR} - S \)) の整数値に最も近いゼロ。以来(Y(W_ {curが} \ )\) 単調であり、それはチタンに直接指し示します。

\(1 ^ {\ CIRC} \クワッド\)\(Y(W_} {CUR) - S \ GEQ 0 \) \(CUR W_} {\)大転送れ、小さすぎます。

\(2 ^ {\ CIRC} \クワッド\)\(Y(W_} {CUR) - S <0 \) \(CUR W_}は{\)が大きすぎる、それは小さなを転送します。

↓次にちょうどヒット\(Y(W_ {CUR} )\) 、関数を爆発。長い時間のカード用にもまだここに、また間違った暴力指数の始まりのさえ言葉遣い

inline ll FY1(ll curW)
{
    ll Y=0,cnt_j=0,sumv_of_range=0;
    for(int i=1;i<=m;i++)
    {
        cnt_j=0;
        sumv_of_range=0;
        for(int j=L[i];j<=R[i];j++)
        {
            if(w[j]>=curW)
            {
                cnt_j++;
                sumv_of_range+=v[j];
            }
        }
        Y+=sumv_of_range*cnt_j;
    }
    return Y;
}

ここでのアイデアは、2つのプレフィックス配列最適化することは困難ではない(pre_n []、pre_vは[\ ] \) であることができます。

しかし、それぞれの呼び出しない方法\(Y-(CUR W_は{})\)、\ (pre_n []、pre_v [] \)が再計算されてはなりません。しかし、速度が非常に速く、元を超えています。

コードを参照してください。

コード:

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
inline int read()
{
    char c=getchar();int x=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        x=x*10+c-'0';
    return x;
}
const int N=200010;
const ll LLINF=0x3f3f3f3f3f3f3f3f;
int v[N],w[N],L[N],R[N];
ll n,m,S;
ll pre_n[N],pre_v[N];

// inline ll FY1(ll curW)
// {
//     ll Y=0,cnt_j=0,sumv_of_range=0;
//     for(int i=1;i<=m;i++)
//     {
//         cnt_j=0;
//         sumv_of_range=0;
//         for(int j=L[i];j<=R[i];j++)
//         {
//             if(w[j]>=curW)
//             {
//                 cnt_j++;
//                 sumv_of_range+=v[j];
//             }
//         }
//         Y+=sumv_of_range*cnt_j;
//     }
//     return Y;
// }

inline ll FY(int curW)
{
    ll Y=0;
    memset(pre_n,0,sizeof(pre_n));
    memset(pre_v,0,sizeof(pre_v));
    for(int i=1;i<=n;i++)
    {
        if(w[i]>=curW)
        {
            pre_n[i]=pre_n[i-1]+1;
            pre_v[i]=pre_v[i-1]+v[i];
        }
        else
        {
            pre_n[i]=pre_n[i-1];
            pre_v[i]=pre_v[i-1];
        }
    }
    for(int i=1;i<=m;i++)
        Y+=(pre_n[R[i]]-pre_n[L[i]-1])*(pre_v[R[i]]-pre_v[L[i]-1]);
    return Y;
}

int main()
{
    //freopen("C:\\Users\\Administrator\\Downloads\\testdata (2).in","r",stdin);
    ll minw=LLINF,maxw=0;

    cin>>n>>m>>S;
    for(int i=1;i<=n;i++)
    {
        w[i]=read();
        v[i]=read();
        if(maxw<w[i])maxw=w[i];
        if(minw>w[i])minw=w[i];
    }
    for(int i=1;i<=m;i++)
    {
        L[i]=read();
        R[i]=read();
    }
    ll l=minw-1,r=maxw+2,mid,ans=LLINF;
    while(l<=r)
    {
        mid=((l+r)>>1);
        ll Y=FY(mid);
        if(Y>=S)l=mid+1;
        else r=mid-1;
        ans=min(ans,llabs(S-Y));
    }
    printf("%lld",ans);

    return 0;
}

おすすめ

転載: www.cnblogs.com/kion/p/11823449.html