[2019年11月8日]幸せな結婚生活の訓練学校

[タイトル]まとめ

線形道路に加えて、開始と終了の合計\(N- \)指定された点\(N + 1 \)道路区間の長さ\(W_i \) および交通信号灯の各交点における期間、すべての交通信号灯期間は同じ、緑色光の持続時間である\(G \) 赤色期間\(R&LT \)

車交差点を通過するとき、それが赤色光で停止した場合、次の緑色光までであろう。

今、与えられた\(M \)車の開始時間を\(T_I \) 目的地に到達するための最短時間を見つけます。

[思考]ポイント

  • 我々は二つのサブ問題の問題に分けることができますので、期間のすべての交通信号は、同じです。最初の信号機によって停止される前に、その後、停止しました。
  • 最初のサブタスク:
  • 我々は簡単に、接頭辞と2つずつの間の距離を計算して記録(SUM [I] = \ ^ SUM _ {I} = {J}。1 w_j \)\
  • 最初によって\(I \)十分な条件は、交通信号で停止:\((T_S + SUM [I])\ BMOD(G + R&LT)> G \) (もともと最初に\(グラム\) sが交通信号を持つことができますが、一度にラベルを傷つける\(G \)彼女が停止したとき秒)
  • 与えるために、元の式の開始後の最小数を維持するために重みを有する我々は、セグメントツリー\((T_S \ BMOD(G + R)+和[I] \ BMOD(G + R))\ BMOD(G + R)\) 。
  • この場合は、もし説明した2つのケースに分けることができる\(T_S \のLeq G \) 次いで追加\([I]和\ MOD (G + R)\) 超えることができない\(G \) このよう唯一のいくつかの答えは、間隔([G-T_S、MOD-1-T_S] \)\
  • そうでない場合には、二つの部分があり、\([0、MOD-1 -t_s] \) と\([mod-(t_s-(1-G))+ 1 ,. 1-MOD] \)
  • 私たちがすることができ、第2のサブタスク(DP \)を\解決します。
  • オーダー\(G [i]には、\)を表しから\(I \)最短時間緑色光通りの終わりに開始します。
  • 伝達方程式は:\(G [I] = G [J] + DIS(I、J)+(G-R&LT DIS +(I、J)\ BMOD(G + R&LT))\)
  • 前記\(J \)された\(I \)最初の後には、交通信号で停止しました。
  • 我々はまた、奥から手前に、上記実施に似使用\(DP \)重みセグメントツリー最適化するために使用される、\(DPを\) 即ち固定された\(SUM [I] \ BMOD(G + R&LT)\) そして、答えの最小間隔見つける\(Jを\) (基本的に後方の数をカウント)
  • 実際には、2 \(和[I] \ BMOD (G + R)\) と\(和[J] \ BMOD (G + R)\) 線分ツリーから\(\ GE G \) 変換厳密に\(> G-1 \) 私達はちょうど私たちが必要な範囲を持っていないので。
  • もし\(和[I] \ BMOD (G + R)-1 <(G + R)-1 \) も示し、不要なセグメントである連続した期間の間隔が:\([SUM [I] \ BMOD(G R&LT +)、SUM [I] \ BMOD(R&LT + G)+。1-G] \) クエリ部に対する回答を2つに分割されている\([和[I] \ BMOD(G + R)+ G 、MOD-1] \)\([0、SUM [I] \ BMOD(G + R&LT)-1] \)
  • そうでなければ不要なセクションは、2つになり、我々のクエリ間隔はながらなった\([(SUM [i]は 、\ BMOD(G + R)+1 \ BMOD(G + R)+ G-1) (SUM [I] \ BMOD(G + R&LT)-1] \)
  • 時間計算\(\ mathcal {O}( M \倍ログ(G + R))\)

[コード]

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f3f3f3f3f

using namespace std;

typedef long long ll;

template <typename T> void chkmax(T& x, T y) { x = x > y ? x : y; }
template <typename T> void chkmin(T& x, T y) { x = x < y ? x : y; }

const int N = 2e5 + 5;
ll w[N], sum[N], dp[N];
int n, g, r;
ll mod;

ll getDis(int i, int j) {
  if (i > j)
    return 0;
  return sum[j] - sum[i];
}

#define lc (tr[nod].ch[0])
#define rc (tr[nod].ch[1])

struct Node {
  int ch[2];
  ll val;
} tr[N * 32];
 
int root, tot = 0;

void pushup(int nod) {
  tr[nod].val = INF;
  if (lc) 
    chkmin(tr[nod].val, tr[lc].val);
  if (rc)
    chkmin(tr[nod].val, tr[rc].val);
}

void insert(int& nod, ll l, ll r, ll k, int v) {
  if (!nod)
     tr[nod = ++tot].val = INF;
  if (l == r) {
    tr[nod].val = v;
    return;
  }
  ll mid = (l + r) >> 1;
  if (k <= mid) 
    insert(lc, l, mid, k, v);
  else 
    insert(rc, mid + 1, r, k, v);
  pushup(nod);
}

ll query(int nod, ll l, ll r, ll ql, ll qr) {
  if (!nod)
    return INF;
  if (ql <= l && r <= qr)
    return tr[nod].val;
  ll mid = (l + r) >> 1, res = INF;
  if (ql <= mid)
    chkmin(res, query(lc, l, mid, ql, qr));
  if (qr > mid)
    chkmin(res, query(rc, mid + 1, r, ql, qr));
  return res;
}

ll queryPos1(ll sumi) {
  sumi %= mod;
  ll res = INF;
  if (sumi + g - 1 < mod - 1) {
    ll t1 = query(root, 0, mod - 1, sumi + g, mod - 1);
    ll t2 = query(root, 0, mod - 1, 0, sumi - 1);
    chkmin(res, t1), chkmin(res, t2);
  }
  else 
    chkmin(res, query(root, 0, mod - 1, (sumi + g - 1) % mod + 1, sumi - 1));
  return res;
}

ll queryPos2(ll t0) {
  t0 %= mod;
  ll res = INF;
  if (t0 <= g)
    chkmin(res, query(root, 0, mod - 1, g - t0, mod - 1 - t0));
  else {
    chkmin(res, query(root, 0, mod - 1, 0, mod - 1 - t0));
    chkmin(res, query(root, 0, mod - 1, mod - (t0 - (g - 1)) + 1, mod - 1));
  } 
  return res;
}

int main() {
  ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  cin >> n >> g >> r;
  mod = g + r;
  for (int i = 1; i <= n + 1; i++) 
    cin >> w[i];
  sum[0] = 0;
  for (int i = 1; i <= n + 1; i++)
    sum[i] = sum[i - 1] + w[i];
  dp[n + 1] = w[n + 1];
  for (int i = n; i >= 1; i--) {
    ll pos = queryPos1(sum[i]);
    if (pos == INF)
      dp[i] = getDis(i, n + 1);
    else {
      ll Dis = getDis(i, pos);
      dp[i] = dp[pos] + Dis + (mod - Dis % mod);
    }
    insert(root, 0, mod - 1, sum[i] % mod, i);
  }
  int q; cin >> q;
  while (q--) {
    int t0; cin >> t0;
    ll pos = queryPos2(t0);
    if (pos == INF)
      cout << t0 + sum[n + 1] << '\n';
    else {
      ll tmp = getDis(0, pos);
      cout << t0 + tmp + (mod - (t0 + tmp) % mod) + dp[pos] << '\n';
    }
  }
  return 0;
}

おすすめ

転載: www.cnblogs.com/chhokmah/p/11828202.html