倒木

タイトル説明

シャオフアはダリンから木を伐採するように呼ばれ、長さmメートルの木材を伐採する必要がありました。今、Xiaohuaは奇妙な伐採機を持っています。伐採機の作業プロセスは次のとおりです。Xiaohuaは高さパラメーターh(メートル)を設定し、伐採機は巨大な鋸刃を高さhまで上げ、木のすべての部分をhより高く切断します(もちろん、木hメートル以下である部品は変更されません)。Xiaohuaは木の切断部分を取得します。
たとえば、並木の高さが20、15、10、17メートルの場合、暁華は鋸刃を15メートルの高さに上げます。切断後、残りの木の高さは15、15、10になります。 、および15メートル。Huaは最初の木から5メートル、4番目の木から2メートル、合計7メートルの木材を取得します。
Xiaohuaは生態系の保護に非常に関心を持っているので、あまり多くの木材を伐採することはありません。これが彼がフェラーブレードをできるだけ高く設定した理由です。Xiaohuaが入手できる木材が少なくともmメートルになるように、Xiaohuaが木材のこぎりの刃の最大整数高さhを見つけるのを手伝ってください。言い換えれば、彼がさらに1メートル上げると、mメートルの木材を手に入れることはできません。

入力フォーマット

2つの整数nとmの最初の行。nは木の数を表し、mは必要な木材の全長を表します。
2行目のn個の整数は各ツリーの高さを表し、値は109を超えません。すべての木材の長さの合計がmより大きいことを確認してください。そうすれば、解決策が必要になります。

出力フォーマット

1行あたりの整数は、伐採された木の最高の高さを示します。

入力サンプル

5 20
4 42 40 26 46

サンプル出力

36

請求

データの30%について、1≤n≤10、1≤m≤30。
データの70%について、1≤n≤103、1≤m≤104。
データの100%の場合、1≤n≤106、1≤m≤2×109。

激しく列挙したところ、コンパイルしたところ、サンプルのみが使用されており、自分でコンパイルしたデータは一切使用されていませんでした(少し酸っぱいです~~~)。その後、答えは次のようになります。タイトルは見つける必要があるため、2つの部分最短距離の最大値がこの種の問題に最も適しています。

2点

ここに画像の説明を挿入

二分法は、英語-中国語辞書から単語を検索する必要があると言っているようなものです。最初から最後までページごとに検索します。こうすることで確実に見つけることができますが、最悪の場合は向きを変える必要があります。辞書全体で。それは面倒です。
それを改善する方法はありますか?もちろんあります。

辞書を中央で分割し、中央のページの主要な単語を見て、探している単語を左半分にするか右半分にするかを決定し、その部分に移動して方法を検討します。それを見つけるために。同様に、他の部分も分割して判断します。このように続ければ、答えをすばやく見つけることができ、辞書全体を調べる必要はありません。

ページごとに検索すると、最大n回検索できることが証明できますが、この方法では、最大でfloor(log2n)回検索できます。
この方法を「2点回答」と呼びます。名前が示すように、バイナリメソッドで回答を列挙し、列挙時に回答が実行可能かどうかを判断します。ただし、二分法はすべての状況で利用できるわけではなく、二分法を使用するには2つの条件を満たす必要があります。1つは有界で、もう1つは単調です。

バイナリ回答は、単調な閉区間で実行する必要があります。言い換えれば、バイナリ回答に対する最終的な回答は、検索のような複数のソリューションではなく、特定の値である必要があります。二分法は、一般的に最適解問題を解くために使用されます。単調性について話しましたが、この単調性はどこに反映されるべきでしょうか?

このように考えてみてください。間隔にはたくさんの数字があります。これらの数字は私たちの問題の解決策かもしれません。言い換えれば、多くの違法な解決策と多くの合法的な解決策があります。私たちは合法的な解決策のみを検討し、それらを実行可能な解決策と呼びます。すべての実行可能な解決策を考慮して、これらの実行可能な解決策の中から最良のものを答えとして見つける必要があります。この答えを最適解と呼びます。

最適解は実行可能でなければなりませんが、実行可能解は必ずしも最適ではありません。シーケンス全体が単調であり、数xが実行可能解であると仮定します。一般に、すべてのx '(x' <x)が実行可能解です。そして、数yに違法な解がある場合、一般に、すべてのy '(y'> y)は違法な解です。

—————————————————————————————————————————

本旨

質問の意味を分析します。切り取った木の高さが一列に並んだ最も高い木の高さである場合、切り取った木の長さは0です。また、伐採木の高さが0、つまり地面の高さの場合、すべての樹木が伐採されます。質問の意味から、この値はmより大きくなければなりません。その後、伐採高さhを徐々に上げていきますが、明らかに、伐採量は徐々に減少していきます。変化の法則は次のとおりです。hが「単調に」上昇すると、「単調に」伐採される木材の量が減少します。このように、hが一定の高さまで上がると、伐採量は必要な値mより少なくなります。この高さから1を引いた位置が必要です。

伐採高さや伐採総量の変化は単調であるため、「2点解答」法により、樹木伐採高の最高値を迅速に決定することができます。2つのパーティション間の左端点lowは0に設定され、右端点highは最も高いツリーの高さに設定され、間隔の中点はmid =(low + high + 1)/ 2であり、midは伐採する木の高さ、およびn本の樹木を線形にスキャンします。樹木を伐採した合計を計算します。合計がm以上の場合は、間隔の左端を中央に更新します。これは、より高い樹木伐採高さを引き続き試すことができるためです。合計がm未満の場合、midは要件を満たしていないため、樹木の伐採高さを下げる必要があるため、間隔の右端がmid-1に更新されます。左右の間隔が重なると、検索は終了します。間隔の左端は毎回要件を満たすことが保証されているため、質問への回答としてlowが返されます。アルゴリズムの時間計算量はO(n log2(max(h)))であり、空間計算量はO(n)です。

—————— ACコード

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+99;
int n,m,ans,l=1,r;
int a[maxn];
bool js(int k){
    
    
    long long d=0;
    for (int i=1;i<=n;i++)
        if (a[i]>k) d+=a[i]-k;
    if (d>=m) return true;
	return false;
}
int main(){
    
    
    cin>>n>>m;
    for (int i=1;i<=n;i++){
    
    
        cin>>a[i];
        if (a[i]>r) r=a[i];
    }
    while (l<=r){
    
    
        int mid=(l+r)/2;
        if (js(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    cout<<ans;
	return 0; 
}

———— QAQ

コンピュータルームでのダラオの独特のアイデア-WA !!!

まず、n本の木を低いものから高いものへと並べ替えます。次に、高から低にスキャンします。隣接する2つの樹木の間に高さの差がある場合は常に、下の樹木の高さが樹木伐採の高さと見なされます。伐採量と前回の伐採高さの合計を維持します。各伐採後に追加される新しい木材の量は、前の2つの伐採の高さの差に、現在の樹木の後の樹木の数を掛けたものです。このように、連続スキャンの過程で、伐採された木の高さは徐々に減少し、伐採された木材の総量は徐々に増加します。一定の高さで伐採された木材の総量がmを超えると、数学的な計算を使用して、どのくらいの高さを上げる必要があるかを知ることができます。これにより、最後に伐採された木の高さは、「伐採された木の高さはできるだけ高い」。このアルゴリズムの時間計算量はO(n log2n)であり、空間計算量はO(n)です。

私は才能がなく、コードを取得できませんでした。
危険 - - -

おすすめ

転載: blog.csdn.net/qq_46258139/article/details/112983123