//gemini3.1pro #include #include #include #include using namespace std; void solve() { int n; long long k; cin >> n >> k; vector A(n), B(n), C(n), D(n); for (int i = 0; i < n; i++) cin >> A[i]; for (int i = 0; i < n; i++) cin >> B[i]; for (int i = 0; i < n; i++) cin >> C[i]; for (int i = 0; i < n; i++) cin >> D[i]; // 売却の選択肢を管理するプール {価格, 個数} map pool; long long total_pool = 0; long long max_profit = 0; // 後ろの日付から逆順に処理 for (int i = n - 1; i >= 0; i--) { // 1. その日の売却枠をプールに追加 if (D[i] > 0) { pool[C[i]] += D[i]; total_pool += D[i]; } // 2. その日の購入枠を使って、最も高い売却枠と貪欲にマッチング long long to_buy = B[i]; long long matched = 0; while (to_buy > 0 && !pool.empty()) { auto it = prev(pool.end()); // 最も価格が高い選択肢 long long price = it->first; long long count = it->second; // 利益が出ないなら終了 if (price <= A[i]) break; long long take = min(to_buy, count); max_profit += take * (price - A[i]); matched += take; to_buy -= take; total_pool -= take; if (count == take) { pool.erase(it); } else { it->second -= take; } } // マッチングした分だけ「キャンセル権」として A[i] の売却枠を追加 if (matched > 0) { pool[A[i]] += matched; total_pool += matched; } // 3. 前日に持ち越せるのは最大 K 個なので、安い選択肢から捨てる while (total_pool > k && !pool.empty()) { auto it = pool.begin(); // 最も価格が安い選択肢 long long count = it->second; long long excess = total_pool - k; if (count <= excess) { total_pool -= count; pool.erase(it); } else { it->second -= excess; total_pool -= excess; break; } } } // 最初から 10^100 ゴールド持っている前提で増えた分だけ出力 cout << max_profit << "\n"; } int main() { // 高速な入出力 ios_base::sync_with_stdio(false); cin.tie(NULL); int t; if (cin >> t) { while (t--) { solve(); } } return 0; }