ferinの競プロ帳

競プロについてのメモ

yukicoder 595 登山

問題ページ
No.595 登山 - yukicoder

考えたこと

  1. ARC067 D - Walk and Teleportを思い出す
  2. 同じように貪欲にできないかなとか考える
  3. 間を開けて歯抜けの状態で先に進んだほうがいいことはなさそう
  4. ワープして戻るときは単調増加しているできるだけ先のに進んで戻るのが最善そう
  5. 右に隣接しているやつに進むパターンとワープして戻るパターンで良い方を貪欲に選ぶみたいなのを書く
  6. 落ちる
    ーーー解説を読むーーー
  7. 右に進む区画と左に進む区画の2パターンを持ってDPしないといけない
  8. 右に隣接してるやつに進むときにワープしたほうが良いパターンが抜けてたりして色々と雑なコードを書いていた
  9. 漸化式通り実装すると通る

f:id:ferin_tech:20171111135713j:plain

//#define __USE_MINGW_ANSI_STDIO 0
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VL;
typedef vector<VL> VVL;
typedef pair<int, int> PII;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define IN(a, b, x) (a<=x&&x<b)
#define MP make_pair
#define PB push_back
#ifdef int
const ll INF = (1LL<<60);
#else
const int INF = (1LL<<30);
#endif
const double PI = 3.14159265359;
const double EPS = 1e-12;
const int MOD = 1000000007;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

int h[200010], dp[2][200010];
signed main(void)
{
  int n, p;
  cin >> n >> p;
  REP(i, n) cin >> h[i];

  REP(i, 2) REP(j, n) dp[i][j] = INF;
  dp[0][0] = 0;

  FOR(i, 1, n) {
    dp[0][i] = min(min(dp[0][i-1], dp[1][i-1])+p, dp[0][i-1] + max(0LL, h[i]-h[i-1]));
    dp[1][i] = min(min(dp[0][i-1], dp[1][i-1])+p, dp[1][i-1] + max(h[i-1]-h[i], 0LL));
  }

  // REP(i, 2) {
  //   REP(j, n) cout << dp[i][j] << " ";
  //   cout << endl;
  // }

  cout << min(dp[0][n-1], dp[1][n-1]) << endl;

  return 0;
}