#include using namespace std; using int64 = long long; using i128 = __int128_t; struct SegTree { int n; const vector* vals; // 1-indexed compressed actual values vector cnt; vector sum; SegTree() {} SegTree(int n, const vector* vals) : n(n), vals(vals) { cnt.assign(4 * n + 5, 0); sum.assign(4 * n + 5, 0); } void add(int node, int l, int r, int idx, int64 delta) { if (l == r) { cnt[node] += delta; sum[node] += delta * (int64)(*vals)[l]; return; } int mid = (l + r) >> 1; if (idx <= mid) add(node << 1, l, mid, idx, delta); else add(node << 1 | 1, mid + 1, r, idx, delta); cnt[node] = cnt[node << 1] + cnt[node << 1 | 1]; sum[node] = sum[node << 1] + sum[node << 1 | 1]; } void add(int idx, int64 delta) { if (delta == 0) return; add(1, 1, n, idx, delta); } // remove up to k largest elements in [ql, qr] pair removeLargest(int node, int l, int r, int ql, int qr, int64 &k) { if (k == 0 || r < ql || qr < l || cnt[node] == 0) return {0, 0}; if (ql <= l && r <= qr && cnt[node] <= k) { int64 rc = cnt[node]; int64 rs = sum[node]; cnt[node] = 0; sum[node] = 0; k -= rc; return {rc, rs}; } if (l == r) { int64 take = min(k, cnt[node]); cnt[node] -= take; sum[node] -= take * (int64)(*vals)[l]; k -= take; return {take, take * (int64)(*vals)[l]}; } int mid = (l + r) >> 1; auto right = removeLargest(node << 1 | 1, mid + 1, r, ql, qr, k); auto left = removeLargest(node << 1, l, mid, ql, qr, k); cnt[node] = cnt[node << 1] + cnt[node << 1 | 1]; sum[node] = sum[node << 1] + sum[node << 1 | 1]; return {left.first + right.first, left.second + right.second}; } pair removeLargest(int ql, int qr, int64 k) { if (ql > qr || k <= 0) return {0, 0}; return removeLargest(1, 1, n, ql, qr, k); } // remove up to k smallest elements in [ql, qr] pair removeSmallest(int node, int l, int r, int ql, int qr, int64 &k) { if (k == 0 || r < ql || qr < l || cnt[node] == 0) return {0, 0}; if (ql <= l && r <= qr && cnt[node] <= k) { int64 rc = cnt[node]; int64 rs = sum[node]; cnt[node] = 0; sum[node] = 0; k -= rc; return {rc, rs}; } if (l == r) { int64 take = min(k, cnt[node]); cnt[node] -= take; sum[node] -= take * (int64)(*vals)[l]; k -= take; return {take, take * (int64)(*vals)[l]}; } int mid = (l + r) >> 1; auto left = removeSmallest(node << 1, l, mid, ql, qr, k); auto right = removeSmallest(node << 1 | 1, mid + 1, r, ql, qr, k); cnt[node] = cnt[node << 1] + cnt[node << 1 | 1]; sum[node] = sum[node << 1] + sum[node << 1 | 1]; return {left.first + right.first, left.second + right.second}; } pair removeSmallest(int ql, int qr, int64 k) { if (ql > qr || k <= 0) return {0, 0}; return removeSmallest(1, 1, n, ql, qr, k); } int64 totalCount() const { return cnt[1]; } }; static void print_i128(i128 x) { if (x == 0) { cout << 0 << '\n'; return; } string s; while (x > 0) { int d = (int)(x % 10); s.push_back(char('0' + d)); x /= 10; } reverse(s.begin(), s.end()); cout << s << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int N; int64 K; cin >> N >> K; vector A(N + 1), C(N + 1); vector B(N + 1), D(N + 1); for (int i = 1; i <= N; i++) cin >> A[i]; for (int i = 1; i <= N; i++) cin >> B[i]; for (int i = 1; i <= N; i++) cin >> C[i]; for (int i = 1; i <= N; i++) cin >> D[i]; vector xs; xs.reserve(2 * N); for (int i = 1; i <= N; i++) { xs.push_back(A[i]); xs.push_back(C[i]); } sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(), xs.end()), xs.end()); vector vals(1, 0); // 1-indexed for (int v : xs) vals.push_back(v); auto getIdx = [&](int v) { return (int)(lower_bound(xs.begin(), xs.end(), v) - xs.begin()) + 1; }; int M = (int)xs.size(); SegTree seg(M, &vals); i128 answer = 0; for (int i = N; i >= 1; i--) { int idxC = getIdx(C[i]); int idxA = getIdx(A[i]); // 1) add D_i copies of C_i seg.add(idxC, D[i]); // 2) remove largest values > A_i, up to B_i auto rem = seg.removeLargest(idxA + 1, M, B[i]); int64 removedCnt = rem.first; int64 removedSum = rem.second; // 3) add profit, then insert A_i removedCnt times answer += (i128)removedSum - (i128)removedCnt * (i128)A[i]; seg.add(idxA, removedCnt); // 4) keep only top K marginals int64 excess = seg.totalCount() - K; if (excess > 0) { seg.removeSmallest(1, M, excess); } } print_i128(answer); } return 0; }