#include using namespace std; using ll = long long; // One-shot experiment: defer a duet when an unchosen, higher-scoring solo // for either participant is available in the same state. constexpr int SMALL_BEAM_WIDTH = 128; constexpr int LARGE_BEAM_WIDTH = 18; constexpr int PERSON[6][2] = {{0, -1}, {1, -1}, {2, -1}, {0, 1}, {0, 2}, {1, 2}}; using Key = unsigned __int128; constexpr int BITS = 19; // Each count is at most N_MAX = 300000. constexpr Key MASK = (Key(1) << BITS) - 1; int count_at(Key key, int t) { return int((key >> (BITS * (5 - t))) & MASK); } struct CountHash { size_t operator()(Key key) const { uint64_t lo = uint64_t(key), hi = uint64_t(key >> 64); uint64_t x = lo ^ (hi + 0x9e3779b97f4a7c15ULL + (lo << 6) + (lo >> 2)); x ^= x >> 30; x *= 0xbf58476d1ce4e5b9ULL; x ^= x >> 27; x *= 0x94d049bb133111ebULL; return size_t(x ^ (x >> 31)); } }; struct State { Key count = 0; ll score = 0; }; void solve() { int n; array stamina; cin >> n >> stamina[0] >> stamina[1] >> stamina[2]; const int beam_width = n >= 10000 ? LARGE_BEAM_WIDTH : SMALL_BEAM_WIDTH; array, 6> value; for (int i = 0; i < n; ++i) { int type; ll score; cin >> type >> score; value[type - 1].push_back(score); } for (auto &a : value) sort(a.rbegin(), a.rend()); vector beam(1); vector answer; for (int depth = 1; depth <= n; ++depth) { vector candidates; candidates.reserve(beam.size() * 6); for (const State &s : beam) { int c[6]; for (int t = 0; t < 6; ++t) c[t] = count_at(s.count, t); int used[3] = {c[0] + c[3] + c[4], c[1] + c[3] + c[5], c[2] + c[4] + c[5]}; for (int t = 0; t < 6; ++t) { if (c[t] == (int)value[t].size()) continue; int a = PERSON[t][0], b = PERSON[t][1]; if (used[a] == stamina[a] || (b != -1 && used[b] == stamina[b])) continue; if (b != -1) { ll duet = value[t][c[t]]; if ((c[a] < (int)value[a].size() && value[a][c[a]] > duet) || (c[b] < (int)value[b].size() && value[b][c[b]] > duet)) continue; } State next = s; next.score += value[t][c[t]]; next.count += Key(1) << (BITS * (5 - t)); candidates.push_back(next); } } if (candidates.empty()) break; unordered_set seen; seen.reserve(candidates.size()); vector distinct; distinct.reserve(candidates.size()); for (const State &s : candidates) { if (seen.insert(s.count).second) distinct.push_back(s); } candidates = move(distinct); const int keep = min(beam_width, candidates.size()); partial_sort(candidates.begin(), candidates.begin() + keep, candidates.end(), [](const State &a, const State &b) { if (a.score != b.score) return a.score > b.score; return a.count < b.count; }); candidates.resize(keep); answer.push_back(candidates.front().score); beam = move(candidates); } cout << answer.size(); for (ll x : answer) cout << ' ' << x; cout << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int test_cases; cin >> test_cases; while (test_cases--) solve(); }