#include "migrations.h"
#include <bits/stdc++.h>
using namespace std;
#define forsn(i, s, n) for (int i = int(s); i < int(n); i++)
#define forn(i, n) forsn(i, 0, n)
#define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--)
#define dforn(i, n) dforsn(i, 0, n)
using vi = vector<int>;
using ll = long long;
using ii = pair<int, int>;
#define fst first
#define snd second
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define pb push_back
#define eb emplace_back
const int N = 10000, K = 15;
int up[K][N], depth[N];
int lca(int u, int v) {
if (depth[u] < depth[v]) swap(u, v);
int diff = depth[u] - depth[v];
forn(i, K) if (diff >> i & 1) u = up[i][u];
if (u == v) return u;
dforn(i, K) if (up[i][u] != up[i][v]) {
u = up[i][u], v = up[i][v];
}
assert(up[0][u] == up[0][v]);
return up[0][u];
}
int dist(int u, int v) {
return depth[u] + depth[v] - 2 * depth[lca(u, v)];
}
const int MOVES = 8;
const int B[MOVES] = {140, 20, 6, 2, 2, 1, 1, 1};
const int T[MOVES] = {-1, 1, 1, 1, 1, 2, 3, 4};
int D[MOVES];
int u, v;
vi candidatesU, candidatesV;
int indice, value;
void reduce(vi &c, int v, int l) {
vi new_c;
forn(i, sz(c)) {
if (i / l == v) new_c.pb(c[i]);
}
c = new_c;
}
int getBase(int g) {
int base = T[g] == 1 ? (int) sqrt(B[g] * 4 + 1) : 5;
if (T[g] == -1) {
base = 1;
while ((base + 2) * (base + 1) / 2 <= B[g] * 4 + 1) base++;
}
return base;
}
int send_message(int /*N*/, int i, int Pi) {
if (i == 1) {
depth[0] = 0;
forn(j, K) up[j][0] = 0;
u = 0, v = 0;
candidatesU.pb(0), candidatesV.pb(0);
D[MOVES - 1] = B[MOVES - 1];
dforn(j, MOVES - 1) D[j] = D[j + 1] + B[j];
}
up[0][i] = Pi, depth[i] = depth[Pi] + 1;
forn(j, K - 1) up[j + 1][i] = up[j][up[j][i]];
if (dist(i, u) > dist(u, v)) v = i;
else if (dist(i, v) > dist(u, v)) u = i;
candidatesU.pb(i), candidatesV.pb(i);
if (i < N - D[0]) return 0;
if (i <= N - D[0] && u > v) swap(u, v);
forn(g, MOVES) if (i == N - D[g]) {
int idxU = 0, idxV = 0;
while (candidatesU[idxU] != u) idxU++;
while (candidatesV[idxV] != v) idxV++;
int base = getBase(g);
int lenU = (sz(candidatesU) + base - 1) / base;
int lenV = (sz(candidatesV) + base - 1) / base;
int sectionU = idxU / lenU;
assert(sectionU < base);
int sectionV = idxV / lenV;
assert(sectionV < base);
if (T[g] <= 2) reduce(candidatesU, sectionU, lenU);
if (T[g] % 2 != 0) reduce(candidatesV, sectionV, lenV);
if (T[g] == -1) {
assert(sectionU <= sectionV);
assert(base * (base + 1) / 2 <= B[g] * 4 + 1);
int number = sectionV * (sectionV + 1) / 2 + sectionU - 1;
indice = number == -1 ? 0 : number / 4;
assert(indice < B[g]);
value = number % 4 + 1;
continue;
}
if (T[g] == 1) {
int number = sectionU * base + sectionV - 1;
indice = number == -1 ? 0 : number / 4;
assert(indice < B[g]);
value = number % 4 + 1;
} else if (T[g] == 2) value = sectionU;
else if (T[g] == 3) value = sectionV;
else {
int idx = 0;
forn(i, sz(candidatesU)) forn(j, sz(candidatesV)) {
if (candidatesU[i] == candidatesV[j]) continue;
if (candidatesU[i] == u && candidatesV[j] == v) value = idx;
idx++;
}
}
}
forn(g, MOVES) if (i == N - D[g] + indice) return value;
return 0;
}
ii longest_path(vi S) {
D[MOVES - 1] = B[MOVES - 1];
dforn(j, MOVES - 1) D[j] = D[j + 1] + B[j];
vi candidatesU, candidatesV;
forn(i, N) {
candidatesU.pb(i), candidatesV.pb(i);
forn(g, MOVES) if (i == N - D[g]) {
int indice = -1, value = -1;
forsn(j, i, i + B[g]) if (S[j] || (indice == -1 && j == i + B[g] - 1)) {
indice = j - i;
value = S[j];
}
int base = getBase(g);
int lenU = (sz(candidatesU) + base - 1) / base;
int lenV = (sz(candidatesV) + base - 1) / base;
int number = value == 0 ? -1 : indice * 4 + (value - 1);
number++;
int sectionU = T[g] == 1 ? number / base : value;
int sectionV = T[g] == 1 ? number % base : value;
if (T[g] == -1) {
sectionV = 0;
while ((sectionV + 1) * (sectionV + 2) / 2 <= number) sectionV++;
sectionU = number - sectionV * (sectionV + 1) / 2;
}
if (T[g] <= 2) reduce(candidatesU, sectionU, lenU);
if (T[g] % 2 != 0) reduce(candidatesV, sectionV, lenV);
if (T[g] == 4) {
int idx = 0;
forn(i, sz(candidatesU)) forn(j, sz(candidatesV)) {
if (candidatesU[i] == candidatesV[j]) continue;
if (idx == value) return {candidatesU[i], candidatesV[j]};
idx++;
}
}
}
}
assert(false);
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |