ABC475 C - Walk the Line

直線上の散歩

考え方

うろうろする方法はいろいろある。
しかし、一度行った町を再訪する意味がないことを考えると、調べる候補を削ることができる。
つまり、左に行って右に行ってまた左、のように $2$ 回以上折り返すのは意味がない。
一方向に進むだけ、または $1$ 回だけ折り返して $S$ を通過して反対へ行く場合、だけ考えれば十分。
しかも、折り返しまでの距離が $0$ と考えることで前者は後者に吸収できる。

ということで、折り返し位置を動かしながらゴール地点も動かす尺取法が成立する。
折り返し位置までで既に距離がオーバーするようになったら打ち切り。
あるいは、折り返した後 $S$ まで戻ることすらできなくなった場合も打ち切りでよい。

これを $S$ から左右どちらに出発するかで $2$ 回やって、最大値を答えればよい。
計算量は $O(N)$ である。

尺取法の際、毎回 $A$ の値を足し引きしてもよいが、累積和で町の位置を出しておくと書きやすくなる。

入力例1での動作

入力を受け取る。

n: 6
s: 3
l: 10
a: {5, 2, 4, 1, 6}

町の番号は 0-indexed とする。
町 $2$ から出発し、移動できる距離の合計は $10$ 以下である。

各町の位置を累積和で求めると、左から順に $0,5,7,11,12,18$ となる。
出発地点である町 $2$ の位置は $7$ である。

まず、左へ進んでから右へ進む場合を調べる。
左端を $1$ つずつ左へ動かし、距離和が $10$ を超える間は右端も左へ動かす。
左移動距離は出発地点から左端まで、右移動距離は左端から右端までの距離とする。

左端 右端 左移動距離 右移動距離 距離和 判定 町数
$2$ $5$ $0$ $11$ $11$ × —
$2$ $4$ $0$ $5$ $5$ ○ $3$
$1$ $4$ $2$ $7$ $9$ ○ $4$
$0$ $4$ $7$ $12$ $19$ × —
$0$ $3$ $7$ $11$ $18$ × —
$0$ $2$ $7$ $7$ $14$ × —
$0$ $1$ $7$ $5$ $12$ × —
$0$ $0$ $7$ $0$ $7$ ○ $3$

左へ進んでから右へ進む場合、訪問できる町数の最大値は $4$ である。

次に、右へ進んでから左へ進む場合を調べる。
今度は右端を $1$ つずつ右へ動かし、距離和が $10$ を超える間は左端も右へ動かす。
右移動距離は出発地点から右端まで、左移動距離は右端から左端までの距離とする。

左端 右端 左移動距離 右移動距離 距離和 判定 町数
$0$ $2$ $7$ $0$ $7$ ○ $3$
$0$ $3$ $11$ $4$ $15$ × —
$1$ $3$ $6$ $4$ $10$ ○ $3$
$1$ $4$ $7$ $5$ $12$ × —
$2$ $4$ $5$ $5$ $10$ ○ $3$
$2$ $5$ — $11$ — — —

町 $5$ は、出発地点から右へ進むだけで距離が $11$ となるので、ここで探索を打ち切る。
右へ進んでから左へ進む場合、訪問できる町数の最大値は $3$ である。

両方の最大値を比べると、答えは $4$ となる。

注意点

街の位置や移動距離は、int 型からはみ出る。
long long 型を用いること。

別解

「$S$ を挟んでここからここまで」という範囲を全探索すると、計算量が $O(N^2)$ になってしまう。
だが、実は $N$ の上限が $8000$ なので、今回はそれでも間に合う。

指定範囲の街を全て巡る最短距離は、以下の $2$ つの短い方を調べるだけで見つかる。

累積和により町の位置が計算してあれば、候補 $1$ つの判定が $O(1)$ で済む。
よって、全体で計算量は $O(N^2)$ になる。