#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set> #include <stack> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef __int64 ll; const ll Inf = (ll)(1e15); const int N = 1000 + 10; const int M = 50 + 5; struct node { ll addv, min; }; struct tnode { int pos; ll cos; tnode() { } tnode(int _pos, ll _cos) { pos = _pos; cos = _cos; } }; node seg[N << 2]; vector<tnode> a[M]; int val[M][N][2]; ll d[M][N]; void Up(node& fa, node &ls, node& rs) { if (ls.min > rs.min) { fa.min = rs.min; } else { fa.min = ls.min; } } void Down(node& fa, node& ls, node& rs) { if (fa.addv != 0) { ls.min += fa.addv; rs.min += fa.addv; ls.addv += fa.addv; rs.addv += fa.addv; fa.addv = 0; } } void build(int i, int p, int l, int r, int rt) { seg[rt].addv = 0; if (l == r) { seg[rt].min = d[i][l] + abs(p - a[i][l].pos); } else { int mid = (l + r) >> 1; build(i, p, lson); build(i, p, rson); Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]); } } void update(int L, int R, ll v, int l, int r, int rt) { if (L <= l && r <= R) { seg[rt].min += v; seg[rt].addv += v; } else { int mid = (l + r) >> 1; Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1]); if (L > mid) update(L, R, v, rson); else if (R <= mid) update(L, R, v, lson); else { update(L, mid, v, lson); update(mid + 1, R, v, rson); } Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]); } } void update_pos(int i, int j, int from, int to, int l, int r, int rt) { if (l == r) { int p = a[i][j].pos; ll v = (ll)-abs(p - from) + abs(p - to); seg[rt].min += v; seg[rt].addv += v; } else { Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1]); int mid = (l + r) >> 1; if (j <= mid) update_pos(i, j, from, to, lson); else update_pos(i, j, from, to, rson); Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]); } } bool cc(const tnode& i, const tnode& j) { return i.pos < j.pos; } void work() { for (int i = 0; i < M; ++i) a[i].clear(); int m, n, x, st, p, idx, idy; scanf("%d%d%d", &n, &m, &st); for (int i = 1; i <= n; ++i) for (int j = 0; j < m; ++j) scanf("%d", &val[i][j][0]); for (int i = 1; i <= n; ++i) for (int j = 0; j < m; ++j) scanf("%d", &val[i][j][1]); a[0].push_back(tnode(st, 0)); for (int i = 1; i <= n; ++i) { for (int j = 0; j < m; ++j) a[i].push_back(tnode(val[i][j][0], val[i][j][1])); sort(a[i].begin(), a[i].end(), cc); } // dp for (int i = 0; i <= n; ++i) for (int j = 0; j < a[i].size(); ++j) d[i][j] = Inf; d[0][0] = 0; for (int i = 1; i <= n; ++i) { p = a[i][0].pos; build(i - 1, p, 0, a[i - 1].size() - 1, 1); d[i][0] = a[i][0].cos + seg[1].min; // idx = -1; while (idx + 1 < a[i - 1].size() && a[i - 1][idx + 1].pos < p) ++ idx; idy = a[i - 1].size(); while (idy - 1 >= 0 && a[i - 1][idy - 1].pos > p) -- idy; // for (int j = 1; j < a[i].size(); ++j) { while (idy < a[i - 1].size() && a[i - 1][idy].pos <= a[i][j].pos) ++ idy; if (idx >= 0) update(0, idx, a[i][j].pos - p, 0, a[i - 1].size() - 1, 1); if (idy < a[i - 1].size()) update(idy, a[i - 1].size() - 1, p - a[i][j].pos, 0, a[i - 1].size() - 1, 1); // for (int k = idx + 1; k < idy; ++k) update_pos(i - 1, k, p, a[i][j].pos, 0, a[i - 1].size() - 1, 1); // d[i][j] = a[i][j].cos + seg[1].min; p = a[i][j].pos; while (idx + 1 < a[i - 1].size() && a[i - 1][idx + 1].pos < p) ++ idx; } } ll ans = Inf; for (int i = 0; i < a[n].size(); ++i) ans = min(ans, d[n][i]); cout << ans << endl; } int main() { int cas; scanf("%d", &cas); while (cas -- > 0) work(); return 0; }