#include <bits/stdc++.h>
#include "algotester.h"
// #include "algotester_generator.h"
using namespace std;
#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define RFOR(i,b,a) for (int i = (b) - 1; i >= (a); i--)
#define ITER(it,a) for (__typeof(a.begin()) it = a.begin(); it != a.end(); it++)
#define FILL(a,value) memset(a, value, sizeof(a))
#define SZ(a) (int)a.size()
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;
const double PI = acos(-1.0);
const int INF = 1000 * 1000 * 1000 + 7;
const LL LINF = INF * (LL) INF;
const int NUM_NODES = 10, NUM_TYPES = 3, MAX_BATCH_SIZE = 16, MAX_NUM_PACKETS = 100000, MAX_TIME = 10000000;
int cost[NUM_NODES + 1][NUM_TYPES + 1][MAX_BATCH_SIZE + 1];
int batchLimit[NUM_NODES + 1][NUM_TYPES + 1];
int c4, c6, cr;
int n, nout;
struct Packet
{
int type;
int arriveTime;
int departureTime;
int t;
int atNodeId;
int id;
bool operator <(const Packet& other) const
{
return arriveTime < other.arriveTime;
}
};
vector<Packet> packets;
vector<int> packetIndex;
int curTime, queueTime;
map<pair<int, int>, int> nextNode =
{
{{1, 1}, 2},
{{2, 1}, 3},
{{3, 1}, 4},
{{4, 1}, 5},
{{5, 1}, 6},
{{6, 1}, 7},
{{7, 1}, 8},
{{8, 1}, 9},
{{9, 1}, 10},
{{1, 2}, 2},
{{2, 2}, 3},
{{3, 2}, 8},
{{8, 2}, 9},
{{9, 2}, 10},
{{1, 3}, 2},
{{2, 3}, 9},
{{9, 3}, 10}};
void read_test(AlgotesterReader &in, ofstream &user_in)
{
FOR (it, 0, 20)
{
int i = in.readInt();
int j = in.readInt();
int b = in.readInt();
user_in << i << " " << j << " " << b;
// cerr << i << " " << j << " " << b;
batchLimit[i][j] = b;
for (int k = 1; k <= b; k++)
{
cost[i][j][k] = in.readInt();
user_in << " " << cost[i][j][k];
// cerr << " " << cost[i][j][k];
}
user_in << "\n";
// cerr << "\n";
}
c4 = in.readInt();
c6 = in.readInt();
cr = in.readInt();
user_in << c4 << " " << c6 << " " << cr << "\n";
// cerr << c4 << " " << c6 << " " << cr << "\n";
n = in.readInt();
user_in << n << "\n";
// cerr << n << "\n";
user_in.flush();
packets.resize(n);
FOR (i, 0, n)
{
packets[i].id = in.readInt();
packets[i].type = in.readInt();
packets[i].arriveTime = in.readInt();
}
sort(ALL(packets));
packetIndex.resize(n + 1);
FOR (i, 0, SZ(packets))
{
packetIndex[packets[i].id] = i;
}
}
int main(int argc, char *argv[])
{
ios::sync_with_stdio(false); // cin.tie(0);
auto [test_in, user_in, user_out] = initInteractiveChecker(argc, argv);
auto output = ofstream(argv[5]);
auto error = [&user_in]() { user_in << -1 << endl;};
user_out.setErrorCallback(error);
auto checkWithError = [&error](bool condition, string message) { check(condition, message, error); };
read_test(test_in, user_in);
curTime = 1;
int ind = 0;
char errMsg[1005];
while (true)
{
char op = user_out.readChar("RE", true, "op");
if (op == 'R')
{
int t = user_out.readInt(curTime, MAX_TIME, "t");
// cerr << "==> R " << t << "\n";
curTime = t + cr;
int indPrev = ind;
while (ind < n && packets[ind].arriveTime <= t)
{
ind++;
}
user_in << ind - indPrev << "\n";
// cerr << ind - indPrev << "\n";
for (int i = indPrev; i < ind; i++)
{
user_in << packets[i].id << " " << packets[i].type << " " << packets[i].arriveTime << "\n";
// cerr << packets[i].id << " " << packets[i].type << " " << packets[i].arriveTime << "\n";
packets[i].atNodeId = 1;
packets[i].t = curTime;
}
user_in.flush();
}
if (op == 'E') {
int t = user_out.readInt(curTime, MAX_TIME, "t");
int i = user_out.readInt(1, NUM_NODES, "i");
int s = user_out.readInt(1, MAX_BATCH_SIZE, "s");
// cerr << "==> E " << t << ' ' << i << ' ' << s;
vector<int> ids(s);
FOR (k, 0, s)
{
int id = user_out.readInt(1, n, "id_k");
id = packetIndex[id];
ids[k] = id;
// cerr << ' ' << id;
checkWithError(packets[id].atNodeId == i && packets[id].t <= t, "packet is not on a correct node");
checkWithError(packets[id].type == packets[ids[0]].type, "packets have different type in a single batch");
}
// cerr << "\n";
int type = packets[ids[0]].type;
checkWithError(s <= batchLimit[i][type], "incorrect batch size");
curTime = t + cost[i][type][s];
int nextNodeId = nextNode.count({i, type}) ? nextNode[{i, type}] : 0;
FOR (k, 0, s)
{
int id = ids[k];
packets[id].atNodeId = nextNodeId;
// hardware accelerator
if (i == 4 || i == 6)
{
packets[id].t = max(curTime, queueTime) + (i == 4 ? c4 : c6);
queueTime = packets[id].t;
}
else
{
packets[id].t = curTime;
}
}
user_in << "0\n";
// cerr << "0\n";
user_in.flush();
if (i == NUM_NODES) {
nout += s;
FOR (k, 0, s)
{
packets[ids[k]].departureTime = curTime;
}
if (nout >= n) {
break;
}
}
}
}
user_out.readEof();
check(nout == n, "not all packets have been processed");
output << n << "\n";
FOR (i, 0, n)
{
output << packets[i].arriveTime << ' ' << packets[i].departureTime << "\n";
}
return 0;
}