import sys
from dataclasses import dataclass
from typing import List
class FastScanner:
__slots__ = ("buffer", "pos")
def __init__(self):
self.buffer = b""
self.pos = 0
def _fill(self):
chunk = sys.stdin.buffer.read1(1 << 16)
if not chunk:
return False
if self.pos:
self.buffer = self.buffer[self.pos :] + chunk
self.pos = 0
else:
self.buffer += chunk
return True
def next_int(self):
buf = self.buffer
pos = self.pos
while True:
n = len(buf)
while pos < n and buf[pos] <= 32:
pos += 1
if pos < n:
break
self.buffer = buf
self.pos = pos
if not self._fill():
raise EOFError
buf = self.buffer
pos = self.pos
sign = 1
if buf[pos] == 45: # '-'
sign = -1
pos += 1
value = 0
while True:
n = len(buf)
while pos < n:
ch = buf[pos]
if 48 <= ch <= 57:
value = value * 10 + (ch - 48)
pos += 1
else:
self.buffer = buf
self.pos = pos
return sign * value
self.buffer = buf
self.pos = pos
if not self._fill():
return sign * value
buf = self.buffer
pos = self.pos
def make_key(instance_id, query_id):
return (instance_id << 32) ^ (query_id & 0xFFFFFFFF)
@dataclass
class Query:
id: int
cpu: int
mem: int
qto: int
type: int
@dataclass
class Instance:
id: int
level: int
b: int
nodes: List[int]
primary: int
@dataclass
class ServerModel:
id: int
cpu: int
mem: int
cost: int
def main():
fs = FastScanner()
try:
k = fs.next_int()
except EOFError:
return
queries = [None] * k
query_ids = set()
for i in range(k):
q_id = fs.next_int()
q_cpu = fs.next_int()
q_mem = fs.next_int()
q_qto = fs.next_int()
q_type = fs.next_int()
queries[i] = Query(q_id, q_cpu, q_mem, q_qto, q_type)
query_ids.add(q_id)
m = fs.next_int()
instances = [None] * m
primary_by_instance = {}
initial_nodes = []
for i in range(m):
instance_id = fs.next_int()
level = fs.next_int()
b = fs.next_int()
nodes = [0] * b
for j in range(b):
node_id = fs.next_int()
nodes[j] = node_id
initial_nodes.append(node_id)
primary = nodes[0]
instances[i] = Instance(instance_id, level, b, nodes, primary)
primary_by_instance[instance_id] = primary
n = fs.next_int()
models = [None] * n
for i in range(n):
model_id = fs.next_int()
model_cpu = fs.next_int()
model_mem = fs.next_int()
model_cost = fs.next_int()
models[i] = ServerModel(model_id, model_cpu, model_mem, model_cost)
cpu_min = fs.next_int()
mem_min = fs.next_int()
cpu_max = fs.next_int()
mem_max = fs.next_int()
g_cpu = fs.next_int()
g_mem = fs.next_int()
t_lu = fs.next_int()
t_cu = fs.next_int()
t_so = fs.next_int()
_ = t_lu
_ = t_cu
_ = t_so
for _ in range(9):
_dummy = fs.next_int()
t_total = fs.next_int()
target_cpu = cpu_max
target_mem = mem_max
if target_cpu < cpu_min:
target_cpu = cpu_min
if target_mem < mem_min:
target_mem = mem_min
if target_cpu > cpu_min:
steps = (target_cpu - cpu_min) // g_cpu
target_cpu = cpu_min + steps * g_cpu
if target_mem > mem_min:
steps = (target_mem - mem_min) // g_mem
target_mem = mem_min + steps * g_mem
model_id_for_node = -1
best_cost = 1 << 62
for model in models:
if model.cpu >= target_cpu and model.mem >= target_mem:
if model.cost < best_cost:
best_cost = model.cost
model_id_for_node = model.id
if model_id_for_node == -1:
target_cpu = cpu_min
target_mem = mem_min
for model in models:
if model.cpu >= target_cpu and model.mem >= target_mem:
if model.cost < best_cost:
best_cost = model.cost
model_id_for_node = model.id
if model_id_for_node == -1:
return
d_cpu = target_cpu - cpu_min
d_mem = target_mem - mem_min
do_initial_scale = d_cpu != 0 or d_mem != 0
server_by_node = {}
next_server_id = 1_000_000_000
for node_id in initial_nodes:
server_by_node[node_id] = next_server_id
next_server_id += 1
out = sys.stdout
lines = []
lines.append(f"{len(initial_nodes)}\n")
for node_id in initial_nodes:
lines.append(f"{server_by_node[node_id]} {model_id_for_node}\n")
lines.append(f"{len(initial_nodes)}\n")
for node_id in initial_nodes:
lines.append(f"{node_id} {server_by_node[node_id]}\n")
out.write("".join(lines))
out.flush()
try:
verdict = fs.next_int()
except EOFError:
return
if verdict == -1:
return
middleware = {}
for t in range(1, t_total + 1):
try:
rt = fs.next_int()
except EOFError:
return
for _ in range(rt):
instance_id = fs.next_int()
query_id = fs.next_int()
qps = fs.next_int()
key = make_key(instance_id, query_id)
middleware[key] = middleware.get(key, 0) + qps
cnt_new = 0
cnt_del = 0
cnt_local = len(initial_nodes) if (t == 1 and do_initial_scale) else 0
cnt_cross = 0
cnt_out = 0
lines = []
lines.append(f"{cnt_new} {cnt_del} {cnt_local} {cnt_cross} {cnt_out}\n")
if cnt_local > 0:
for node_id in initial_nodes:
lines.append(f"{node_id} {d_cpu} {d_mem}\n")
dispatches = []
for key, amount in middleware.items():
if amount <= 0:
continue
instance_id = key >> 32
query_id = key & 0xFFFFFFFF
primary_node = primary_by_instance[instance_id]
dispatches.append((instance_id, query_id, primary_node, amount))
lines.append(f"{len(dispatches)}\n")
for instance_id, query_id, node_id, amount in dispatches:
lines.append(f"{instance_id} {query_id} {node_id} {amount}\n")
middleware.clear()
out.write("".join(lines))
out.flush()
try:
verdict = fs.next_int()
except EOFError:
return
if verdict == -1:
return
if __name__ == "__main__":
main()