クエリxiを処理した際に、動かさなかったほうのコマが位置yにある場合の最短時間をdp[i][y]とせよ。この時、コマは位置xiとyにある。ここからクエリxi+1を処理するとき、コマをxi→xi+1と移動させ、yのコマを動かさないなら
dp[i+1][y]=dp[i][y]+∣xi−xi+1∣(1)
y→xi+1と移動させ、xiのコマを動かさないなら
dp[i+1][xi]=ymin(dp[i][y]+∣y−xi+1∣)(2)
これで計算できる形になっているので、初期化をdp[1][B]:=∣x1−A∣,dp[1][A]:=∣x1−B∣、それ以外は+∞としてDPすれば答えは求まる。ただ、このままでは間に合わないので遷移を工夫する必要がある。
(2)の右辺は、次のように絶対値を外して書ける:
dp[i+1][xi]:=min{miny≥xi+1(dp[i][y]+y)−xi+1miny<xi+1(dp[i][y]−y)+xi+1
それぞれのminはたぶんセグメント木等で得られる形になっているので、dpを1次元のセグメント木にしてO(logN)で遷移できそう。具体的には、
T:=min{miny≥xi+1(dp[y]+y)−xi+1miny<xi+1(dp[y]−y)+xi+1(3)
を求めたあと、dp全体に∣xi−xi+1∣を加算し、最後にdp[xi]:=Tと更新し直せばよい。
悩んだのは(3)の計算をどう実現するかで、テクニックを知らなかったのでもっとも直接的な扱い方をした:
セグメント木の元を((y+,d+),(y−,d−))と4値で持ち、演算を
((y1+,d1+),(y1−,d1−))⊕((y2+,d2+),(y2−,d2−))=((y1+,d1+)と(y2+,d2+)のうちy1++d1+,y2++d2+の小さいほう,(y1−,d1−)と(y2−,d2−)のうちy1−−d1−,y2−−d2−の小さいほう)
で定める。値Δの区間加算は
((y+,d+),(y−,d−))↦((y++Δ,d+),(y−+Δ,d−))
でよい。
これでACできたが、素朴すぎて定数倍がかなり重かった。
skyさんの解説にもっとスマートな方法が載っていた。最初からdpl[y]:=dp[y]+N−y,dpr[y]:=dp[y]+yみたいに補正したものを用意すればよいらしい。なるほど……