#include using namespace std; using ll = long long; const ll INF = 1LL << 60; // 間隔 d の状態から、片側を合計 x だけ逆向きに動かすための最小操作回数 ll calc(ll x, ll d) { ll sum = 0; int k = 0; while (sum < x) { sum = sum * 2 + d; ++k; } return k; } // RL ペアを逆向きに愚直再帰する。 // 現在の間隔が D、左側・右側をあと A, B だけ逆向きに動かす。 ll solve_pair(ll A, ll B, ll D) { if (A == 0) return calc(B, D); if (B == 0) return calc(A, D); ll res = INF; // 次に左側を動かす if (A <= D) { // 1 回で左側が完成 res = min(res, 1 + calc(B, D + A)); } else { // 完成しないなら D だけ動かしてよい res = min(res, 1 + solve_pair(A - D, B, 2 * D)); } // 次に右側を動かす if (B <= D) { // 1 回で右側が完成 res = min(res, 1 + calc(A, D + B)); } else { // 完成しないなら D だけ動かしてよい res = min(res, 1 + solve_pair(A, B - D, 2 * D)); } return res; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int Q; cin >> Q; while (Q--) { int N, M; cin >> N >> M; vector> A(M); for (auto& [s, g] : A) cin >> s; for (auto& [s, g] : A) cin >> g; sort(A.begin(), A.end()); // 到達可能性 bool ok = true; for (int i = 1; i < M; ++i) { auto [s1, g1] = A[i - 1]; auto [s2, g2] = A[i]; if (g1 > g2 || (g1 == g2 && !(s1 == s2 && s1 == g1))) { ok = false; break; } } if (!ok) { cout << -1 << '\n'; continue; } // 1: R, -1: L, 0: S vector type(M); for (int i = 0; i < M; ++i) { auto [s, g] = A[i]; if (s < g) type[i] = 1; if (s > g) type[i] = -1; } vector paired(M); ll ans = 0; // RL ペア for (int i = 0; i + 1 < M; ++i) { if (type[i] == 1 && type[i + 1] == -1) { paired[i] = paired[i + 1] = true; auto [s1, g1] = A[i]; auto [s2, g2] = A[i + 1]; ll X = g1 - s1; ll Y = s2 - g2; ll D = g2 - g1; ans += solve_pair(X, Y, D); } } // RL ペアに含まれないもの for (int i = 0; i < M; ++i) { if (paired[i]) continue; auto [s, g] = A[i]; if (type[i] == 1) { if (i + 1 == M) { ++ans; } else { ans += calc( g - s, A[i + 1].second - g ); } } if (type[i] == -1) { if (i == 0) { ++ans; } else { ans += calc( s - g, g - A[i - 1].second ); } } } cout << ans << '\n'; } }