#include using namespace std; using int64 = long long; // min { k >= 0 : total <= gap * 2^k } // total > 0, gap > 0 int doublingCount(int64 total, int64 gap) { unsigned long long x = static_cast((total - 1) / gap); if (x == 0) { return 0; } return 64 - __builtin_clzll(x); } // 逆操作で、左側が先に初期位置へ到達する場合。 // left > 0, right > 0, gap > 0 int firstLeftCost(int64 left, int64 right, int64 gap) { const int64 total = left + gap + right; const int64 A = (left + gap - 1) / gap; const int64 B = (right + gap - 1) / gap; int best = INT_MAX; int t = 0; for (int64 p = 1; p * gap < total; p *= 2, ++t) { const int64 low = max(0LL, p - A); const int64 high = min({ p - 1, B - 1, 2 * p - 1 - A }); if (low > high) { continue; } // b は大きいほど、その後の間隔が広くなる。 const int64 width = left + (high + 1) * gap; const int cost = t + 1 + doublingCount(total, width); best = min(best, cost); } return best; } int convergingCost(int64 left, int64 right, int64 gap) { return min( firstLeftCost(left, right, gap), firstLeftCost(right, left, gap) ); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int Q; cin >> Q; while (Q--) { int64 N; int M; cin >> N >> M; vector> elevators(M); for (auto& elevator : elevators) { cin >> elevator.first; } for (auto& elevator : elevators) { cin >> elevator.second; } // 初期位置の昇順、同じなら目標位置の昇順。 sort(elevators.begin(), elevators.end()); bool possible = true; for (int i = 1; i < M; ++i) { const auto [prevS, prevG] = elevators[i - 1]; const auto [s, g] = elevators[i]; if (prevG > g) { possible = false; break; } if (prevG == g && (prevS != prevG || s != g)) { possible = false; break; } } if (!possible) { cout << -1 << '\n'; continue; } int64 answer = 0; for (int i = 0; i < M; ++i) { const auto [s, g] = elevators[i]; if (s == g) { continue; } if (s < g) { // 右向きの直後が左向きなら、ペアとして処理。 if (i + 1 < M && elevators[i + 1].first > elevators[i + 1].second) { const auto [nextS, nextG] = elevators[i + 1]; answer += convergingCost( g - s, nextS - nextG, nextG - g ); ++i; } else if (i + 1 == M) { // 右側に他のエレベーターがない。 ++answer; } else { const int64 nextG = elevators[i + 1].second; answer += doublingCount( nextG - s, nextG - g ); } } else { // 左隣が右向きの場合は、すでにペア処理済み。 if (i == 0) { ++answer; } else { const int64 prevG = elevators[i - 1].second; answer += doublingCount( s - prevG, g - prevG ); } } } cout << answer << '\n'; } return 0; }