#include #include typedef long long i64; static int *g_vals; static i64 *seg_cnt; static i64 *seg_sum; static unsigned char *seg_lazy; static inline int next_int(void) { int c = getchar_unlocked(); while (c <= ' ') c = getchar_unlocked(); int x = 0; while (c > ' ') { x = x * 10 + (c - '0'); c = getchar_unlocked(); } return x; } static int cmp_int(const void *pa, const void *pb) { int a = *(const int *)pa; int b = *(const int *)pb; return (a > b) - (a < b); } static void bit_add(i64 *bit, int n, int idx, i64 delta) { while (idx <= n) { bit[idx] += delta; idx += idx & -idx; } } static i64 bit_sum(const i64 *bit, int idx) { i64 s = 0; while (idx > 0) { s += bit[idx]; idx -= idx & -idx; } return s; } static int bit_kth(const i64 *bit, int n, int topbit, i64 k) { int idx = 0; for (int step = topbit; step > 0; step >>= 1) { int nxt = idx + step; if (nxt <= n && bit[nxt] < k) { idx = nxt; k -= bit[nxt]; } } return idx + 1; } static int lower_bound_int(const int *arr, int n, int x) { int lo = 0; int hi = n; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (arr[mid] < x) lo = mid + 1; else hi = mid; } return lo; } static inline void seg_clear(int node) { seg_cnt[node] = 0; seg_sum[node] = 0; seg_lazy[node] = 1; } static inline void seg_pull(int node) { seg_cnt[node] = seg_cnt[node << 1] + seg_cnt[node << 1 | 1]; seg_sum[node] = seg_sum[node << 1] + seg_sum[node << 1 | 1]; } static inline void seg_push(int node) { if (!seg_lazy[node]) return; seg_clear(node << 1); seg_clear(node << 1 | 1); seg_lazy[node] = 0; } static void seg_add_point(int node, int l, int r, int idx, i64 delta) { if (l == r) { seg_cnt[node] += delta; seg_sum[node] += (i64)g_vals[l] * delta; seg_lazy[node] = 0; return; } seg_push(node); int mid = (l + r) >> 1; if (idx <= mid) seg_add_point(node << 1, l, mid, idx, delta); else seg_add_point(node << 1 | 1, mid + 1, r, idx, delta); seg_pull(node); } static i64 seg_query_prefix_count(int node, int l, int r, int q) { if (q < l || seg_cnt[node] == 0) return 0; if (r <= q) return seg_cnt[node]; seg_push(node); int mid = (l + r) >> 1; return seg_query_prefix_count(node << 1, l, mid, q) + seg_query_prefix_count(node << 1 | 1, mid + 1, r, q); } static i64 seg_remove_small(int node, int l, int r, i64 need) { if (need == 0 || seg_cnt[node] == 0) return 0; if (need >= seg_cnt[node]) { i64 ret = seg_sum[node]; seg_clear(node); return ret; } if (l == r) { seg_cnt[node] -= need; i64 dec = (i64)g_vals[l] * need; seg_sum[node] -= dec; return dec; } seg_push(node); int mid = (l + r) >> 1; i64 take_left = seg_cnt[node << 1] < need ? seg_cnt[node << 1] : need; i64 ret = seg_remove_small(node << 1, l, mid, take_left); ret += seg_remove_small(node << 1 | 1, mid + 1, r, need - take_left); seg_pull(node); return ret; } static i64 seg_remove_large(int node, int l, int r, i64 need) { if (need == 0 || seg_cnt[node] == 0) return 0; if (need >= seg_cnt[node]) { i64 ret = seg_sum[node]; seg_clear(node); return ret; } if (l == r) { seg_cnt[node] -= need; i64 dec = (i64)g_vals[l] * need; seg_sum[node] -= dec; return dec; } seg_push(node); int mid = (l + r) >> 1; i64 take_right = seg_cnt[node << 1 | 1] < need ? seg_cnt[node << 1 | 1] : need; i64 ret = seg_remove_large(node << 1 | 1, mid + 1, r, take_right); ret += seg_remove_large(node << 1, l, mid, need - take_right); seg_pull(node); return ret; } int main(void) { int T = next_int(); while (T--) { int N = next_int(); i64 K = next_int(); int *a = (int *)malloc((size_t)N * sizeof(int)); int *b = (int *)malloc((size_t)N * sizeof(int)); int *c = (int *)malloc((size_t)N * sizeof(int)); int *d = (int *)malloc((size_t)N * sizeof(int)); int *vals = (int *)malloc((size_t)(2 * N) * sizeof(int)); for (int i = 0; i < N; ++i) { a[i] = next_int(); vals[i] = a[i]; } for (int i = 0; i < N; ++i) b[i] = next_int(); for (int i = 0; i < N; ++i) { c[i] = next_int(); vals[N + i] = c[i]; } for (int i = 0; i < N; ++i) d[i] = next_int(); qsort(vals, (size_t)(2 * N), sizeof(int), cmp_int); int m = 0; for (int i = 0; i < 2 * N; ++i) { if (i == 0 || vals[i] != vals[i - 1]) { vals[m++] = vals[i]; } } int *aid = (int *)malloc((size_t)N * sizeof(int)); int *cid = (int *)malloc((size_t)N * sizeof(int)); for (int i = 0; i < N; ++i) { aid[i] = lower_bound_int(vals, m, a[i]) + 1; cid[i] = lower_bound_int(vals, m, c[i]) + 1; } g_vals = vals - 1; seg_cnt = (i64 *)calloc((size_t)(m * 4 + 5), sizeof(i64)); seg_sum = (i64 *)calloc((size_t)(m * 4 + 5), sizeof(i64)); seg_lazy = (unsigned char *)calloc((size_t)(m * 4 + 5), sizeof(unsigned char)); i64 total = 0; i64 profit = 0; for (int i = N - 1; i >= 0; --i) { if (d[i] > 0) { seg_add_point(1, 1, m, cid[i], d[i]); total += d[i]; } i64 profitable = total - seg_query_prefix_count(1, 1, m, aid[i]); i64 take = b[i] < profitable ? b[i] : profitable; if (take > 0) { i64 removed = seg_remove_large(1, 1, m, take); profit += removed - (i64)a[i] * take; seg_add_point(1, 1, m, aid[i], take); } i64 excess = total - K; if (excess > 0) { seg_remove_small(1, 1, m, excess); total -= excess; } } printf("%lld\n", profit); free(seg_lazy); free(seg_sum); free(seg_cnt); free(cid); free(aid); free(vals); free(d); free(c); free(b); free(a); } return 0; }