#include <vector>
#include <algorithm>
using namespace std;
// 倍增 LCA 及树深维护,N 最大 10000
static int depth[10005];
static int up[14][10005];
// 在线直径和内部状态维护
static int U_node = 0, V_node = 0, D_tree = 0;
static int max_dist_0 = 0, furthest_from_0 = 0;
static int protocol = 0;
static long long B_star = 0;
static long long id_val = 0;
static int bit_idx = 0;
// O(log N) 查询两点距离
int get_lca(int u, int v) {
if (depth[u] < depth[v]) swap(u, v);
int diff = depth[u] - depth[v];
for (int j = 0; j < 14; j++) {
if ((diff >> j) & 1) u = up[j][u];
}
if (u == v) return u;
for (int j = 13; j >= 0; j--) {
if (up[j][u] != up[j][v]) {
u = up[j][u];
v = up[j][v];
}
}
return up[0][u];
}
int get_dist(int u, int v) {
return depth[u] + depth[v] - 2 * depth[get_lca(u, v)];
}
// ============== 研究团队函数 ==============
int send_message(int N, int i, int Pi) {
// 首次调用,复位所有内部静态状态
if (i == 1) {
depth[0] = 0;
for (int j = 0; j < 14; j++) up[j][0] = 0;
U_node = 0; V_node = 0; D_tree = 0;
max_dist_0 = 0; furthest_from_0 = 0;
protocol = 0; B_star = 0; id_val = 0; bit_idx = 0;
}
// 倍增表更新
depth[i] = depth[Pi] + 1;
up[0][i] = Pi;
for (int j = 1; j < 14; j++) {
up[j][i] = up[j-1][up[j-1][i]];
}
int dist0 = get_dist(i, 0);
bool dist0_inc = false;
if (dist0 > max_dist_0) {
dist0_inc = true;
max_dist_0 = dist0;
furthest_from_0 = i;
}
int dU = get_dist(i, U_node);
int dV = get_dist(i, V_node);
bool increased = false;
int replaced = 0;
int max_d = max(dU, dV);
// 若当步节点使得树直径延长,立刻进行贪心更迭
if (max_d > D_tree) {
increased = true;
D_tree = max_d;
if (dU > dV) {
replaced = 1; // 距离 U 较远,意味着新节点取代了原始 V
V_node = i;
} else {
replaced = 2; // 距离 V 较远,意味着新节点取代了原始 U
U_node = i;
}
}
// N-50 步时,判定接下来采取哪个协议传输(同时规避恶意长链)
if (i == N - 50) {
if (U_node == 0 || V_node == 0) {
protocol = 1;
} else {
protocol = 2;
// 注意:绝不可重排序 U_node 与 V_node 以免与后期的抢占指令冲突混淆
id_val = U_node * 10000LL + V_node;
bit_idx = 0;
}
}
if (i == N - 15 && protocol == 1) {
B_star = furthest_from_0;
bit_idx = 0;
}
// ====== 发送消息:严格限制 Z <= 4 ======
// 协议 2:50 步防连击高稳缓冲法
if (protocol == 2 && i >= N - 50) {
if (increased) {
return replaced == 1 ? 3 : 4;
} else {
if (bit_idx < 27) {
long long b = (id_val >> bit_idx) & 1;
bit_idx++;
return b + 1;
}
}
}
// 协议 1:Subtask 1 特供轻量级编码法
if (protocol == 1 && i >= N - 14) {
if (dist0_inc) return 3; // 信号 3 意为:覆盖成为最新的远端点
if (bit_idx < 14) {
int d_i = (B_star >> bit_idx) & 1;
bit_idx++;
return d_i + 1;
}
}
return 0; // 静默隐身状态避免提前招惹评测机
}
// ============== 博物馆函数 ==============
std::pair<int, int> longest_path(std::vector<int> S) {
int N = S.size();
bool is_p2 = false;
// 辨别协议:Protocol 2 从 N-50 就开始发了,Protocol 1 是 N-14 才开始
for (int i = N - 50; i < N - 14; i++) {
if (S[i] > 0) is_p2 = true;
}
if (is_p2) {
long long id = 0;
int b_idx = 0;
int final_U = -1, final_V = -1;
for (int i = N - 50; i < N; i++) {
if (S[i] == 3) {
final_V = i;
} else if (S[i] == 4) {
final_U = i;
} else if (S[i] == 1 || S[i] == 2) {
if (b_idx < 27) {
id |= ((long long)(S[i] - 1) << b_idx);
b_idx++;
}
}
}
int initial_U = id / 10000;
int initial_V = id % 10000;
if (final_U == -1) final_U = initial_U;
if (final_V == -1) final_V = initial_V;
return {final_U, final_V};
} else {
int V = 0;
int last_update = -1;
int b_idx = 0;
for (int i = N - 14; i < N; i++) {
if (S[i] == 3) {
last_update = i;
} else if (S[i] == 1 || S[i] == 2) {
if (b_idx < 14) {
V |= ((S[i] - 1) << b_idx);
b_idx++;
}
}
}
if (last_update != -1) V = last_update;
return {0, V};
}
}