#include <bits/stdc++.h>
using namespace std;
struct Query {
int id;
long long cpu;
long long mem;
long long qto;
int type;
};
struct Instance {
int id;
int level;
int b;
vector<int> nodes;
int primary;
};
struct ServerModel {
int id;
long long cpu;
long long mem;
long long cost;
};
static long long makeKey(int instanceId, int queryId) {
return (static_cast<long long>(instanceId) << 32) ^ static_cast<unsigned int>(queryId);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int k;
if (!(cin >> k)) return 0;
vector<Query> queries(k);
unordered_set<int> queryIds;
queryIds.reserve(k * 2 + 1);
for (int i = 0; i < k; ++i) {
cin >> queries[i].id >> queries[i].cpu >> queries[i].mem >> queries[i].qto >> queries[i].type;
queryIds.insert(queries[i].id);
}
int m;
cin >> m;
vector<Instance> instances(m);
unordered_map<int, int> primaryByInstance;
primaryByInstance.reserve(m * 2 + 1);
vector<int> initialNodes;
initialNodes.reserve(1000);
for (int i = 0; i < m; ++i) {
cin >> instances[i].id >> instances[i].level >> instances[i].b;
instances[i].nodes.resize(instances[i].b);
for (int j = 0; j < instances[i].b; ++j) {
cin >> instances[i].nodes[j];
initialNodes.push_back(instances[i].nodes[j]);
}
instances[i].primary = instances[i].nodes[0];
primaryByInstance[instances[i].id] = instances[i].primary;
}
int n;
cin >> n;
vector<ServerModel> models(n);
for (int i = 0; i < n; ++i) {
cin >> models[i].id >> models[i].cpu >> models[i].mem >> models[i].cost;
}
long long cpuMin, memMin, cpuMax, memMax, gCpu, gMem;
cin >> cpuMin >> memMin;
cin >> cpuMax >> memMax;
cin >> gCpu >> gMem;
int Tlu, Tcu, Tso;
cin >> Tlu >> Tcu >> Tso;
for (int i = 0; i < 9; ++i) {
int dummy;
cin >> dummy;
}
int T;
cin >> T;
long long targetCpu = cpuMax;
long long targetMem = memMax;
if (targetCpu < cpuMin) targetCpu = cpuMin;
if (targetMem < memMin) targetMem = memMin;
// Deltas must be granularity-aligned; if needed, round down to the largest reachable spec.
if (targetCpu > cpuMin) {
long long steps = (targetCpu - cpuMin) / gCpu;
targetCpu = cpuMin + steps * gCpu;
}
if (targetMem > memMin) {
long long steps = (targetMem - memMin) / gMem;
targetMem = memMin + steps * gMem;
}
int modelIdForNode = -1;
long long bestCost = (1LL << 62);
for (const auto& model : models) {
if (model.cpu >= targetCpu && model.mem >= targetMem) {
if (model.cost < bestCost) {
bestCost = model.cost;
modelIdForNode = model.id;
}
}
}
// Fallback to any model that can host Fmin (should always exist on valid tests).
if (modelIdForNode == -1) {
targetCpu = cpuMin;
targetMem = memMin;
for (const auto& model : models) {
if (model.cpu >= targetCpu && model.mem >= targetMem) {
if (model.cost < bestCost) {
bestCost = model.cost;
modelIdForNode = model.id;
}
}
}
}
if (modelIdForNode == -1) {
// No feasible model at all.
return 0;
}
long long dCpu = targetCpu - cpuMin;
long long dMem = targetMem - memMin;
bool doInitialScale = (dCpu != 0 || dMem != 0);
unordered_map<int, int> serverByNode;
serverByNode.reserve(initialNodes.size() * 2 + 1);
int nextServerId = 1000000000;
for (int nodeId : initialNodes) {
serverByNode[nodeId] = nextServerId++;
}
// Initialization round.
cout << initialNodes.size() << '\n';
for (int nodeId : initialNodes) {
cout << serverByNode[nodeId] << ' ' << modelIdForNode << '\n';
}
cout << initialNodes.size() << '\n';
for (int nodeId : initialNodes) {
cout << nodeId << ' ' << serverByNode[nodeId] << '\n';
}
cout.flush();
int verdict;
cin >> verdict;
if (!cin || verdict == -1) return 0;
unordered_map<long long, long long> middleware;
middleware.reserve(1 << 16);
for (int t = 1; t <= T; ++t) {
int rt;
cin >> rt;
if (!cin) return 0;
for (int i = 0; i < rt; ++i) {
int instanceId, queryId;
long long qps;
cin >> instanceId >> queryId >> qps;
long long key = makeKey(instanceId, queryId);
middleware[key] += qps;
}
int cntNew = 0;
int cntDel = 0;
int cntLocal = (t == 1 && doInitialScale) ? static_cast<int>(initialNodes.size()) : 0;
int cntCross = 0;
int cntOut = 0;
cout << cntNew << ' ' << cntDel << ' ' << cntLocal << ' ' << cntCross << ' ' << cntOut << '\n';
if (cntLocal > 0) {
for (int nodeId : initialNodes) {
cout << nodeId << ' ' << dCpu << ' ' << dMem << '\n';
}
}
vector<tuple<int, int, int, long long>> dispatches;
dispatches.reserve(middleware.size());
for (const auto& [key, amount] : middleware) {
if (amount <= 0) continue;
int instanceId = static_cast<int>(key >> 32);
int queryId = static_cast<int>(key & 0xffffffffu);
int primaryNode = primaryByInstance[instanceId];
dispatches.emplace_back(instanceId, queryId, primaryNode, amount);
}
cout << dispatches.size() << '\n';
for (const auto& [instanceId, queryId, nodeId, amount] : dispatches) {
cout << instanceId << ' ' << queryId << ' ' << nodeId << ' ' << amount << '\n';
}
// We dispatch all buffered requests immediately.
middleware.clear();
cout.flush();
cin >> verdict;
if (!cin || verdict == -1) return 0;
}
return 0;
}