fjutacm 3872偽のアルゴリズムの世界最初のバイナリ検索

問題の説明

ある日、ハングマウントPAに起こっている、彼は非常に美しい女の子を見ます

ポイントのほかに、ハング最近の練習は、かわす高速なハードウェアを使用すると、一階のレベルから第二レベルのステップにスキップすることができ一種でかわす、実施するためには、かわす、ハングはとてもまっすぐで、日々のトレーニングを行います------直線上に、第一ハングn個の点をマークし、2点間の距離を算出し、n番目のハングの点は、第1の点からジャンプする必要があります。もしポイントが番目の点LからRへジャンプする場合は、ジャンプ距離がハングとして、[L] + [L + 1] + ... [R-2] + [R-1]であります怠惰、彼はちょうどk個の下にジャンプアップし、各配置が上でなければならないn個の点をマークして、ジャンプは、少なくともこれまでハングジャンプを尋ねるべき?(配置がポイントにマークされなければならない、最も遠い距離をジャンプすることはできません)

 

入力

最初の行は、N、K、1 <= N、K <= 1E5であります

N-1の整数第二列を表し、[I] - > i番目の点Iに最初の点との間の距離+ 1 <= [I] <= 1E5。

 

出力

出力のみの1行は、最大距離にあなたがジャンプに必要なすべての時間を表し

 

SampleInput

6 3 
1 3 2 2 5

SampleOutput

5

1->3 4
3->5 4
5->6 5
最远距离为5

同じ目的でロープをカットし、二分法は、答えを見つけることです - この質問と私は別のブログを書きました。この質問は、コードのアイデアは達成することは比較的容易であるとともに、思考では困難です。

そして、我々は半分の答えに行くようにロープをカットし、回答の条件を満たすように返され、「少なくとも遠くジャンプする必要があります」のタイトルであること、であるステップの必要数、ほとんどの「たびにあなたが最も遠い距離をジャンプする必要があります。」よく読むためにタイトルを読んで、多分意味。

、我々はステップ数を作るために、答えを見つけるしている、可能な限り小さく歩いて、ステップの条件数の場合には、私たちが望む、ポイントを明確にはKを超えることなく、できるだけ大きく、すべてを完了するために必要。

したがって、最初の明確なポイント。それ以外の場合は必要なステップ数が出て、無限、ダイレクトパスとして見ることができますまず、ちょうど小さいライン上の最大値の半分以上の左端、あなたは全体のプロセスを経ることを保証しなければならないので、;ライン上の右の境界の合計よりちょうど大きい、なぜなら多くの大きなステップは、時間を無駄にする必要はすべて同じではありません。ボーダーが等しくない理由については、私はハーフボードを共有するためにブログ、別のブログを行くと見ることができる、首長は書いています。

第二には、私の算術現在のサイズを判断して歩いている、ステップ数は、全体が境界歩行のサイズを縮小するために、ステップ数の条件よりも大きい完了するために必要なので、まず、サイクルは、境界線の交点まで継続させ、解像度をK ==場合は、我々は戻って、歩行の最小サイズを取得することはできません。そして、最初のリラクゼーションゾーンの開始ので、単語「オープン左右オープン」フォームを使用して、そして私たちが望むことは可能歩くだけ小さくなので、あまりにも左の境界線をたるみによる確定申告のRインターチェンジ(ともある「オープン」境界は、それが交差、望ましくないL)で最小値をとります。

次に、コードに、コメントを参照してください。

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <math.h>
#include <iostream>
#include <string.h>
const int MAX=1e5+5;
using namespace std;
typedef long long ll;
ll a[MAX], maxx, sum;
ll td(int n, ll k)
{
  ll l=maxx-1, r=sum+1, m, now;
  int i, j, res;
  while (l+1<r)
  {
    res = 0;  /// 初始化当前解所需步数
    now = 0;  /// 初始化临时跳过的距离
    m = (l+r)/2;
    for (i=1; i<n; i++)  /// 遍历一遍柱子
    {
      if (now+a[i]>m)  /// 这一跳,跳不到下一根柱子了
      {
        now = a[i];   /// 更新位移,从这一根柱子到下一根柱子的距离开始
        res ++;       /// 这一跳算是在这里结束了,记跳了一次
      }
      else
        now += a[i];  /// 能跳过去就加上

      if (res>k)      /// 步履太小,还没跳完步数就超了,直接可以break准备开始
        break;        ///下一次循环了
    }
    if (now)
      res ++;  /// 最后一跳也结算一下
    if (res>k) /// 需要的步数超了,说明步履不够大
      l = m;
    else       /// 反之,说明步履大小还有缩小的可能性
      r = m;
  }
  return r;
}
int main()
{
  ll k;
  int n, i;
  cin >> n >> k;
  maxx = 0;
  sum = 0;
  ll ans=0;
  for (i=1; i<n; i++)
  {
    scanf("%lld", &a[i]);
    maxx = max(maxx, a[i]);
    sum += a[i];
  }
  ans = td(n, k);
//  if (ans>maxx) cout << ans << endl;
//  else cout << maxx << endl;
  cout << ans << endl;
  return 0;
}

 

公開された19元の記事 ウォンの賞賛0 ビュー507

おすすめ

転載: blog.csdn.net/qq_43317133/article/details/98590125