ferinの競プロ帳

競プロについてのメモ

ARC072 E - Alice in linear land

問題ページ

考えたこと

  • まずどんな動きをするのか試してみる
  • 進行方向が反転だったりを考える必要はなくて目的地までの距離だけ使えばよさそう
  • 現在の目的地までの距離をXでd[i]を入力するとX' = min(X, abs(X-d[i])) に変化する
  • Xは単調に減少していくいうことがわかった
  • 書き換えるという動作で何ができるのか
  • まずX'がXより遠い位置になることはない
  • 移動する距離を1~XにすればX'を0~X-1にすることはできる
  • また移動する距離をinfにすればXから移動しないのでXにもできる
  • つまり書き換えるという操作は0~Xのどこかの距離に移動させるという操作になる
  • p番目を書き換えたとき、0~p-1番目の操作をした後の目的地までの距離をYとする
  • p番目では0~Yの距離になる
  • p+1番目以降の操作で目的地にたどり着けない距離があるか?(=0~Yの内に目的地にたどり着けないのがあるか?)が判定できればよい
  • 区間[p+1,n)について考えるので後ろから見たくなる
  • dp[i][j] = (i番目以降の移動で距離jから目的地にたどり着くか?)を考えてdpテーブルを書いてみる
  • たどり着ける点が連続にならんでいるときは最大の値だけ持てばよいのでできそう
  • 不連続なときがよくわからない
  • Dがどこかの範囲で抑えられて空間が大丈夫でインラインDPができるとか考えたけどわからない ----- 解説を見た -----
  • たどり着けない最小の距離だけ持っておけばよいらしく、後ろから見れば解けるらしい

不連続のケースが結局よくわかってないので要復習

#include <bits/stdc++.h>

using namespace std;
using ll = long long;
#define int ll
using PII = pair<int, int>;
template <typename T> using V = vector<T>;
template <typename T> using VV = vector<V<T>>;
template <typename T> using VVV = vector<VV<T>>;

#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 PB push_back

const ll INF = (1LL<<60);
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); }
template <typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }
template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a){
  out<<'('<<a.first<<','<<a.second<<')';
  return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
  out<<'[';
  REP(i, a.size()) {out<<a[i];if(i!=a.size()-1)out<<',';}
  out<<']';
  return out;
}

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

signed main(void)
{
  cin.tie(0);
  ios::sync_with_stdio(false);

  ll n;
  cin >> n;
  vector<ll> v(n+1);
  cin >> v[0];
  REP(i, n) cin >> v[i+1];

  vector<ll> a(n+1);
  a[0] = v[0];
  FOR(i, 1, n+1) a[i] = min(abs(a[i-1]-v[i]), a[i-1]);

  vector<ll> b(n+2);
  b[n+1] = 1;
  for(ll i=n; i>=1; --i) {
    if(min(abs(b[i+1] - v[i]), b[i+1]) == b[i+1]) {
      b[i] = b[i+1];
    } else {
      b[i] = b[i+1] + v[i];
    }
  }

  ll q;
  cin >> q;
  REP(test, q) {
    ll p;
    cin >> p;
    if(b[p+1] <= a[p-1]) {
      cout << "YES" << endl;
    } else {
      cout << "NO" << endl;
    }
  }

  return 0;
}