ロボットは古いDOSベースのゲームをプレイしています。
ゲームにはN + 1の建物があり、0からNまで番号が付けられ、左から右に配置されています。
0番の建物の高さは0単位、i番の建物の高さはH(i)単位です。
当初、ロボットは0番の建物にいました。
各ステップで、次の(右の)建物にジャンプします。
ロボットがk番目の建物にあり、現在のエネルギー値がEであるとすると、次のステップでk +1番目の建物にジャンプします。
H(k + 1)> Eの場合、ロボットはH(k + 1)-Eのエネルギー値を失います。そうでない場合、ロボットはEH(k + 1)のエネルギー値を取得します。
ゲームの目的はN番目の建物に到達することです。このプロセスでは、エネルギー値を負のユニット数にすることはできません。
ここで問題となるのは、少なくともゲームの正常な完了を保証するために、ロボットはどのくらいのエネルギーでゲームを開始する必要があるかということです。
入力形式
最初の行に整数Nを入力します。
2行目は、N個のスペースで区切られた整数です。H(1)、H(2)、...、H(N)は建物の高さを表します。
出力形式
整数を出力します。これは、必要な最小単位の初期エネルギー値を切り上げた結果を表します。
データ範囲
1≤N、H(i)≤105、
入力例1:
5
3 4 3 2 4
出力サンプル1:
4
入力例2:
3
4 4 4
出力サンプル2:
4
入力サンプル3:
3
1 6 4
出力サンプル3:
3
この質問は比較的単純です。これは増加するシーケンスのようです。二分法は直接解決されます。最初のバージョンを作成しました。
#include<iostream>
using namespace std;
const int N=1e5+10,Mod=1e9+7;
int h[N];
int n;
bool check(int m)
{
long long mid=m;
for(int i=1;i<=n;i++)
{
if(h[i]>mid)
mid-=h[i]-mid;
else
mid+=mid-h[i];
mid%=Mod;
if(mid<0)
return false;
}
return true;
}
int main(void)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&h[i]);
int l=0,r=1e5;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l;
}
このテスト例は試していませんが、注意深く観察しましたが、intバーストであることが判明したため、チェック機能を改善しました。
#include<iostream>
using namespace std;
const int N=1e5+10,Mod=1e9+7;
int h[N];
int n;
bool check(int m)
{
long long mid=m;
for(int i=1;i<=n;i++)
{
if(h[i]>mid)
mid-=h[i]-mid;
else
mid+=mid-h[i];
if(mid>1e5+10)
return true;
else if(mid<0)
return false;
}
return true;
}
int main(void)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&h[i]);
int l=0,r=1e5;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l;
}
成功したAC