Submission #1251272

#TimeUsernameProblemLanguageResultExecution timeMemory
1251272jtnydv25Migrations (IOI25_migrations)C++20
0 / 100
857 ms1004 KiB
#include "migrations.h"
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define all(c) ((c).begin()), ((c).end())
#define sz(x) ((int)(x).size())

#ifdef LOCAL
#include <print.h>
#else
#define trace(...)
#define endl "\n" // remove in interactive
#endif

const int N = 10000;
const int logN = 14;

int par[logN][N];
int depth[N];

int lca(int a, int b)
{
  if(depth[a]<depth[b])
  swap(a,b);
  int l = depth[a]-depth[b];
  for(int i = 0;i<logN;i++) if(l&(1<<i)) a = par[i][a];    
  if(a==b)
  return a;
  assert(depth[a] == depth[b]);
  for(int i = logN-1;i>=0;i--)
  if(par[i][a]!=par[i][b])
  {
    a = par[i][a],b = par[i][b];
  }
  return par[0][a];
}

int pathlen(int a, int b){
  return depth[a] + depth[b] - 2 * depth[lca(a, b)];
}

vector<pair<int, int>> pool;
vector<int> L = {221, 13};
const int T1 = N - (4 + 13 + 221);
const int T2 = N - (4 + 13);
const int T3 = N - 4;
int a, b, P, Q, R;
int A, B;

vector<int> message;
int message_pos;
int pos_4;
void get(int ID, int l, int max_non_zero){
    vector<int> msg, pos, pos2, msg2;
    function<void(int)> recurse = [&](int i){
        ID--;
        if(ID == -1){
            msg2 = msg;
            pos2 = pos;
            return;
        }
        if(i == max_non_zero) return;
        // next non-zero
        int prv = i == 0 ? -1: pos[i - 1];
        for(int j = prv + 1; j < l; j++){
            for(int v = 1; v <= 3; v++){
                msg.push_back(v);
                pos.push_back(j);
                recurse(i + 1);
                msg.pop_back();
                pos.pop_back();
            }
        }
    };
    recurse(0);
    // trace(pos2, msg2, ID);
    int j = 0;
    message.resize(l, 0);
    for(int i = 0; i < sz(msg2); i++){
        message[pos2[i]] = msg2[i];
    }
    message_pos = 0;
    pos_4 = -1;
}
vector<vector<int>> cliques_6, cliques_4, paths;
vector<vector<pair<int, int>>> parts;
int id = -1;
int send_message(int n, int i, int Pi) {
  par[0][i] = Pi;
  depth[i] = depth[Pi] + 1;
  for(int j = 1; j < logN; j++) {
    par[j][i] = par[j - 1][par[j - 1][i]];
  }
  int d_ab = pathlen(a, b);
  int d_ia = pathlen(i, a);
  int d_ib = pathlen(i, b);
  if(d_ia >= max(d_ib, d_ab)){
    b = i;
  }
  else if(d_ib >= max(d_ia, d_ab)){
    a = i;
  }
  if(a < b) swap(a, b);
  // trace(i, a, b);
  if(i < T1) return 0;
  if(i == T1){
    A = a; B = b;
    int ID = (a * (a - 1)) / 2 + b;
    get(ID, L[0], 3); // cost = 3
  }

  if(i < T2){
    if(i != T1){
      if(a == i || b == i){
        if(a != A && a != B && b != A && b != B){
          pos_4 = i;
          return 4;
        }
      }
    }
    return message[message_pos++];
  }

  if(i == T2){
    // trace(pos_4);
    // compute the pool
    P = A, Q = B, R = i;
    pool.clear();
    if(pos_4 != -1){
      P = pos_4; Q = pos_4;
    }
    pool.push_back({P, Q});
    pool.push_back({P, R});
    pool.push_back({Q, R});
    for(int j = T1; j < T2; j++){
      pool.push_back({P, j});
      pool.push_back({Q, j});
      pool.push_back({R, j});
    }
    for(auto& it: pool){
      if(it.first < it.second) swap(it.first, it.second);
    }
    sort(all(pool));

    if(a < b) swap(a, b);
    A = a; B = b;
    int ID = -1;
    for(int i = 0; i < pool.size(); i++){
      if(pool[i].first == a && pool[i].second == b){
        ID = i;
        break;
      }
    }
    // trace(A, B);
    assert(ID != -1);
    get(ID, L[1], 2); // cost = 2
  }

  if(i < T3){
    if(i != T2){
      if(a == i || b == i){
        if(a != A && a != B && b != A && b != B){
          pos_4 = i;
          return 4;
        }
      }
    }
    return message[message_pos++];
  }

  
  if(i == T3){
    P = A, Q = B, R = i;
    if(pos_4 != -1){
      P = pos_4; Q = pos_4;
    }
    // cover using K6 graphs
    // T2 + 1, ... i - 1 -- 12 nodes
    // P Q R
    
    cliques_6 = {
      {P, Q, R, T2 + 1, T2 + 2, T2 + 3},
      {P, Q, R, T2 + 4, T2 + 5, T2 + 6},
      {P, Q, R, T2 + 7, T2 + 8, T2 + 9},
      {P, Q, R, T2 + 10, T2 + 11, T2 + 12},
      {P, Q, R, T2 + 1, T2 + 2, T2 + 3}
    };
    // trace(cliques_6);
    // trace(cliques_6, pos_4);
    for(int i = 0; i < 5; i++){
      if(find(all(cliques_6[i]), a) != cliques_6[i].end() &&
          find(all(cliques_6[i]), b) != cliques_6[i].end()){
          id = i;
          break;
        }
    }
    assert(id != -1);
    return id;
  }
  if(i == T3 + 1){
    vector<int> nodes = cliques_6[id];
    nodes.push_back(i);
    cliques_4 = {
      {nodes[0], nodes[1], nodes[2], nodes[3]},
      {nodes[0], nodes[1], nodes[2], nodes[4]},
      {nodes[0], nodes[1], nodes[2], nodes[5]},
      {nodes[0], nodes[1], nodes[2], nodes[6]},
      {nodes[3], nodes[4], nodes[5], nodes[6]}
    };
    // trace(cliques_4);
    id = -1;
    for(int i = 0; i < 5; i++){
      if(find(all(cliques_4[i]), a) != cliques_4[i].end() &&
          find(all(cliques_4[i]), b) != cliques_4[i].end()){
          id = i;
          break;
        }
    }
    assert(id != -1);
    return id;
  }
  if(i == T3 + 2){
    vector<int> nodes = cliques_4[id];
    nodes.push_back(i);
    paths = {
    {1, 0, 4},
    {1, 2, 3},
    {0, 2, 4},
    {3, 4, 1},
    {1, 3, 0}
  }; 
    id = -1;
    for(int ii = 0; ii < paths.size(); ii++){
      vector<int> path = paths[ii];
      vector<int> newpath = path;
      for(int j = 0; j < sz(path); j++){
        newpath[j] = nodes[path[j]];
      }
      vector<pair<int, int>> part;
      for(int j = 0; j + 1 < path.size(); j++){
        int u = nodes[path[j]];
        int v = nodes[path[j + 1]];
        if(u < v) swap(u, v);
        part.push_back({u, v});
        if(a == u && b == v) id = ii;
      }
      paths[ii] = newpath;
      parts.push_back(part);
    }
    // trace(paths, parts);
    assert(id != -1);
    return id;
  }
  vector<pair<int, int>> fin;
  if(i == T3 + 3){
    vector<int> path = paths[id];
    fin = parts[id];
    fin.push_back({path[0], i});
    fin.push_back({path[1], i});
    fin.push_back({path[2], i});
    for(auto& it: fin){
      if(it.first < it.second) swap(it.first, it.second);
    }
    sort(all(fin));
    // trace(fin);
    id = -1;
    for(int j = 0; j < fin.size(); j++){
      if(fin[j].first == a && fin[j].second == b){
        id = j;
        break;
      }
    }
    assert(id != -1);
    // trace(a, b);
    return id;
  }
  return 0;
}

int getID(int l, int max_non_zero) {
    vector<int> msg, pos, pos2, msg2;
    for(int i = 0; i < l; i++) if(message[i] != 0) {
        pos2.push_back(i);
        msg2.push_back(message[i]);
    }
    int ID = -1;
    int cur = -1;
    function<void(int)> recurse = [&](int i){
      cur++;
      if(msg == msg2 && pos == pos2) {
        ID = cur;
        return;
      }
      if(i == max_non_zero) return;
      // next non-zero
      int prv = i == 0 ? -1: pos[i - 1];
      for(int j = prv + 1; j < l; j++){
          for(int v = 1; v <= 3; v++){
              msg.push_back(v);
              pos.push_back(j);
              recurse(i + 1);
              msg.pop_back();
              pos.pop_back();
          }
      }
      
    };
    recurse(0);
    return ID;
}

std::pair<int, int> longest_path(std::vector<int> S) {
  // return {0, 3};
  a, b = 0, 0;
  message.clear();
  pos_4 = -1;
  for(int i = T1; i < T2; i++){
    message.push_back(S[i]);
    if(S[i] == 4) pos_4 = i;
  }
  if(pos_4 != -1){
    P = pos_4; Q = pos_4; R = T2;
  } else{
    int ID = getID(L[0], 3);
    
    for(int _a = 1; _a < N; _a++){
      for(int _b = 0; _b < _a; _b++){
        ID--;
        if(ID == -1){
          a = _a;
          b = _b;
          break;
        }
      }
    }
    P = a; Q = b; R = T2;
  }

  pool.clear();
  pool.push_back({P, Q});
    pool.push_back({P, R});
    pool.push_back({Q, R});
    for(int j = T1; j < T2; j++){
      pool.push_back({P, j});
      pool.push_back({Q, j});
      pool.push_back({R, j});
    }
    for(auto& it: pool){
      if(it.first < it.second) swap(it.first, it.second);
    }
    sort(all(pool));

    message.clear();
    pos_4 = -1;
    for(int i = T2; i < T3; i++){
        message.push_back(S[i]);
        if(S[i] == 4) pos_4 = i;
    }

    if(pos_4 != -1){
      P = pos_4; Q = pos_4; R = T3;
    } else{
      int ID = getID(L[1], 2);
      a = pool[ID].first;
      b = pool[ID].second;
      P = a; Q = b; R = T3;
    }
    cliques_6 = {
      {P, Q, R, T2 + 1, T2 + 2, T2 + 3},
      {P, Q, R, T2 + 4, T2 + 5, T2 + 6},
      {P, Q, R, T2 + 7, T2 + 8, T2 + 9},
      {P, Q, R, T2 + 10, T2 + 11, T2 + 12},
      {P, Q, R, T2 + 1, T2 + 2, T2 + 3}
    };
    // trace(cliques_6, pos_4);
    id = S[T3];
    vector<int> nodes = cliques_6[id];
    nodes.push_back(T3 + 1);
    cliques_4 = {
      {nodes[0], nodes[1], nodes[2], nodes[3]},
      {nodes[0], nodes[1], nodes[2], nodes[4]},
      {nodes[0], nodes[1], nodes[2], nodes[5]},
      {nodes[0], nodes[1], nodes[2], nodes[6]},
      {nodes[3], nodes[4], nodes[5], nodes[6]}
    };
    id = S[T3 + 1];
    nodes = cliques_4[id];
    nodes.push_back(T3 + 2);
    paths = {
      {1, 0, 4},
      {1, 2, 3},
      {0, 2, 4},
      {3, 4, 1},
      {1, 3, 0}
    }; 
    for(int ii = 0; ii < paths.size(); ii++){
      vector<int> path = paths[ii];
      vector<int> newpath = path;
      for(int j = 0; j < sz(path); j++){
        newpath[j] = nodes[path[j]];
      }
      vector<pair<int, int>> part;
      for(int j = 0; j + 1 < path.size(); j++){
        int u = nodes[path[j]];
        int v = nodes[path[j + 1]];
        if(u < v) swap(u, v);
        part.push_back({u, v});
      }
      paths[ii] = newpath;
      parts.push_back(part);
    }
    id = S[T3 + 2];
    vector<int> path = paths[id];
    vector<pair<int, int>> fin = parts[id];
    fin.push_back({path[0], T3 + 3});
    fin.push_back({path[1], T3 + 3});
    fin.push_back({path[2], T3 + 3});
    for(auto& it: fin){
      if(it.first < it.second) swap(it.first, it.second);
    }
    sort(all(fin));
    id = S[T3 + 3];
    // trace(cliques_6, cliques_4, paths, parts, fin);
    return {fin[id].first, fin[id].second};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...