AtCoder ABC089 D
May 8, 2020
https://atcoder.jp/contests/abc089/tasks/abc089_d
解説と別方針で解いたのでメモ。
1個先のマスに移動したときのコストはで計算できるので、N個先に移動したときのコストはダブリングを使ってで計算できる。
実装
#define MAX_H 300
#define MAX_W 300
#define LOG_N 20
using P = pair<i64, i64>;
P C[LOG_N + 1][MAX_H * MAX_W + 10];
int main() {
i64 H, W, D; cin >> H >> W >> D;
i64 N = H * W + 1;
vector<P> Num(N);
REP(y, H) {
REP(x, W) {
i64 a; cin >> a;
Num[a] = P(y, x);
}
}
auto cost = [](const P &p1, const P &p2) {
return abs(p1.first - p2.first) + abs(p1.second - p2.second);
};
REPS(i, N) {
if (i + D >= N) {
C[0][i] = mp(-1, -1);
continue;
}
C[0][i] = mp(i + D, cost(Num[i], Num[i + D]));
}
REP(k, LOG_N) {
REPS(i, N) {
if (C[k][i].first == -1) C[k + 1][i] = mp(-1, -1);
else {
C[k + 1][i] = mp(C[k][C[k][i].first].first,
C[k][i].second + C[k][C[k][i].first].second);
}
}
}
i64 Q; cin >> Q;
while(Q--) {
i64 l, r; cin >> l >> r;
i64 n = (r - l) / D;
i64 cur = l;
i64 s = 0;
REP(k, LOG_N) {
if (cur == -1) break;
if ((n >> k) & 1) {
s += C[k][cur].second;
cur = C[k][cur].first;
}
}
cout << s << endl;
}
return 0;
}