#include "Ali.h"
#include <bits/stdc++.h>
using namespace std;
namespace Ali{
  const int K = 7;
  const int L = 24;
  const int LG = 10;
  const int mxD = 50000;
  const int sz_root = 21;
  const int sz_all = 290;
  // List of Small Tree
  const int sz7 = 5;
  vector<string> T7 = {
    "000011100111", // [0]
    "000011011011", // [1]
    "000001101111", // [2]
    "000110110011", // [3]
    "000011011101"  // [4]
  };
  const int sz6 = 11;
  vector<string> T6 = {
    "0001100111",  // Group 0
    "0001011011",  // Group 1
    "0000111011",  // Group 1
    "0000011111",  // Group 2
    "0000101111",  // Group 2
    "0001101101",  // Group 3
    "0010110011",  // Group 3
    "0001110011",  // Group 3
    "0000110111",  // Group 4
    "0000111101",  // Group 4
    "0001011101"   // Group 4
  };
  vector<int> group = {0,1,1,2,2,3,3,3,4,4,4};
  int get_hash(string hash){
    for(int i=0;i<sz6;i++) if(T6[i]==hash) return i;
    assert(false);
    return -1;
  }
  map<vector<int>,int> root_tree,all_tree;
  int id_all[sz7+5][sz6+5][2*K+5];
  int id_root[sz7+5][sz6+5];
  bool init=false;
  void INIT(){
    //cout << "A_Init" << endl;
    if(init) return;
    memset(id_all,-1,sizeof(id_all));
    memset(id_root,-1,sizeof(id_root));
    init=true;
    for(int b=0;b<sz6;b++) for(int a=group[b];a<sz7;a++){
      string cur="0"+T7[a]+"10"+T6[b]+"1";
      vector<int> deg(2*K);
      vector<vector<int>> edge(2*K);
      int T=0;
      vector<int> x;
      x.push_back(0);
      vector<pair<int,int>> e;
      for(char c:cur){
        if(c=='0'){
          e.push_back({x.back(),++T});
          x.push_back(T);
        }
        else x.pop_back();
      }
      for(auto [u,v]:e){
        deg[u]++,deg[v]++;
        edge[u].push_back(v);
      }
      T=0;
      vector<int> c(2*K,-1);
      queue<int> q;q.push(0);
      while(!q.empty()){
        int u=q.front();q.pop();
        c[u]=T++;
        for(int v:edge[u]) q.push(v);
      }
      for(auto [u,v]:e) edge[v].push_back(u);
      
      vector<bool> ex(2*K);
      if(a==1) ex[3]=true;
      else if(a==2) ex[4]=true;
      else if(a==3) ex[2]=true;
      else if(a==4) ex[1]=ex[3]=true;
      for(int i=0;i<2*K;i++){
        if(deg[i]==3 && !ex[i]) continue;
        vector<int> d(2*K,0);
        function<void(int,int)> dfs = [&](int u,int p){
          for(int v:edge[u]) if(v!=p) d[c[v]]=d[c[u]]+1,dfs(v,u);
        };
        dfs(i,-1);
        if(all_tree.find(d)==all_tree.end()) all_tree[d]=(int)all_tree.size();
        id_all[a][b][c[i]]=all_tree[d];
        if(i==0 && root_tree.find(d)==root_tree.end()) root_tree[d]=(int)root_tree.size();
        if(i==0) id_root[a][b]=root_tree[d];
      }
    }
    assert(sz_root==(int)root_tree.size());
    assert(sz_all==(int)all_tree.size());
    //cout << (int)all_tree.size() << ' ' << (int)root_tree.size() << '\n';
  }
  int cnt=0,M=0,N=0,RT;
  vector<vector<int>> edge,adj;
  vector<bool> head;
  vector<int> f,c,par,dep,root;
  vector<pair<int,int>> pp;
  void Init(int _N, std::vector<int> U, std::vector<int> V) {
    //cout << "Start Init" << endl;
    INIT();
    
    N=_N;
    edge.assign(N,{});
    for(int i=0;i<N-1;i++) edge[U[i]].push_back(V[i]),edge[V[i]].push_back(U[i]);
  
    RT=-1;
    {//Find diameter to determine the farthest vertex from each vertex and use the vertex that has degree <=2 anh the smallest farthest vertex to be the root
      vector<int> d(N),val(N);
      int A=0;
      function<void(int,int)> dfs = [&](int u,int p){
        if(d[u]>d[A]) A=u;
        for(int v:edge[u]) if(v!=p) d[v]=d[u]+1,dfs(v,u);
      };
      dfs(0,-1);
      int X=A;d[X]=0;
      dfs(X,-1);
      for(int i=0;i<N;i++) val[i]=max(val[i],d[i]);
      int Y=A;d[Y]=0;
      dfs(Y,-1);
  
      int mn=N;
      for(int i=0;i<N;i++) if((int)edge[i].size()<=2 && max(val[i],d[i])<mn) RT=i,mn=max(val[i],d[i]);
      assert(mn<=mxD);
    }
    assert(RT!=-1);
    
    head.assign(N,false);
    f.assign(N,-1);
    c.assign(N,-1);
    par.assign(N,-1);
    dep.assign(N,0);
  
    M=N;
    adj.assign(N,{});
    {//Decompose and modify the tree into smaller tree with left and right direct subtree has K-1 vertices without adding a new vertex to a vertex with degree = 2
  
      vector<int> sz(N),leaf(N,-1);
      {//Decompose the tree into each smaller tree of size <2*K  
        
        function<void(int,int)> dfs = [&](int u,int p){
          sz[u]=1,par[u]=p;
          for(int v:edge[u]) if(v!=p) dep[v]=dep[u]+1,dfs(v,u),sz[u]+=sz[v],leaf[u]=leaf[v];
          if(sz[u]>=K) head[u]=true,sz[u]=0;
          if(sz[u]==1) leaf[u]=u;
        };
        dfs(RT,-1);
        if(!head[RT]) head[RT]=true,sz[RT]=0;
  
        function<void(int,int)> dfs2 = [&](int u,int p){
          if(head[u]) f[u]=cnt++;
          else f[u]=f[p];
          for(int v:edge[u]) if(v!=p) dfs2(v,u);
        };
        dfs2(RT,-1);
      }
      //cout << "root: " << RT << '\n';
      {//Add more vertices to the tree to make it a tree with exactly 2*K-1 vertices with 6 vertices left and 6 vertices right
        for(int i=0;i<N;i++) if(!head[i]) adj[par[i]].push_back(i);
  
        
        root.assign(cnt,-1);
        vector<vector<int>> g(cnt);
        
        for(int i=0;i<N;i++){
          g[f[i]].push_back(i);
          if(head[i]) root[f[i]]=i;
        }
        for(int i=0;i<cnt;i++){
          int X=-1;
          for(int v:g[i]) if(head[v]) X=v;
          
          int lt=-1,rt=-1;
          for(int v:adj[X]){
            if(lt==-1) lt=v;
            else rt=v;
          } 
          if(lt==-1) lt=X;
          if(rt==-1) rt=X;
  
          int sl=sz[lt],sr=sz[rt];
          lt=leaf[lt],rt=leaf[rt];
          //cout << sl << ' ' << sr << ' ' << lt << ' ' << rt << endl;
          while(sl<K-1){
            adj[lt].push_back(M);
            adj.push_back({});
            f[M]=i,sl++,lt=M++;
          }
          while(sr<K-1){
            adj[rt].push_back(M);
            adj.push_back({});
            f[M]=i,sr++,rt=M++;
          }
        }
      }
    }
  
    //for(int i=0;i<M;i++) for(int v:adj[i]) cout << "adj " << i << ' ' << v << endl;
    
    pp.assign(cnt,{-1,-1});
    {//Identify the type of left and right subtree and change the larger one to size 7 
      vector<int> sz(M);
      for(int i=0;i<N;i++) if(head[i]){
        function<void(int)> dfs = [&](int u){
          sz[u]=1;
          for(int v:adj[u]) dfs(v),sz[u]+=sz[v];
          if((int)adj[u].size()==2){
            int &x=adj[u][0],&y=adj[u][1];
            if(sz[x]<sz[y]) swap(x,y);
          }
        };
        dfs(i);
  
        string hash;
        function<void(int)> build = [&](int u){
          for(int v:adj[u]){
            hash+='0';
            build(v);
            hash+='1';
          }
        };
        build(adj[i][0]);
        int lt=get_hash(hash);hash.clear();
        build(adj[i][1]);
        int rt=get_hash(hash);hash.clear();
        if(lt<rt){
          swap(lt,rt);
          swap(adj[i][0],adj[i][1]);
        }
  
        
        int id=group[lt],pos=0;
        pp[f[i]]={id,rt};
        
        //cout << lt << ' ' << rt << ' ' << id << endl;
  
        function<void(int)> add = [&](int u){
          //cout << "add " << u << endl;
          for(int v:adj[u]){
            if(T7[id][pos]=='0') pos++;
            add(v);
            assert(T7[id][pos]=='1');
            pos++;
          }
          if(pos<(int)T7[id].size() && T7[id][pos]=='0'){
            //cout << "add " << u << ' ' << M << endl;
            adj[u].push_back(M);
            adj.push_back({});
            f[M]=f[i],M++;
            pos+=2;
          }
        };
        add(adj[i][0]);
  
        int num=0;
        queue<int> q;q.push(i);
        while(!q.empty()){
          int u=q.front();q.pop();
          if(u<N) c[u]=num;
          num++;
          for(int v:adj[u]) q.push(v);
        }
      }
    }
    
    for(int i=0;i<N;i++){
      //cout << "SetId " << i << ' ' << f[i] << ' ' << c[i] << '\n';
      SetID(i,f[i]*2*K+c[i]);
    }
  
    //cout << "End Init" << endl;
  }
  
  std::string SendA(std::string S) {    
    int fX=0,fY=0;
    for(int i=0;i<LG;i++) fX+=(S[i]-'0')<<i,fY+=(S[LG+i]-'0')<<i;
    if(fX>fY) swap(fX,fY);
    
    int val=0;
    if(fX==fY) val=pp[fX].first*sz6+pp[fX].second;
    else{
      val+=sz7*sz6;
      int u=root[fY],dist=0;
      while(u!=-1 && f[u]!=fX) u=par[u],dist++;
      
      if(u==-1){
        dist=0;
        int a=root[fX],b=root[fY];
        if(dep[a]>dep[b]) swap(a,b);
        while(dep[b]!=dep[a]) dist++,b=par[b];
        while(a!=b) dist+=2,a=par[a],b=par[b];
      }
      
      if(dist<=mxD){
        if(u==-1) u=root[fX];
        int b=id_all[pp[fX].first][pp[fX].second][c[u]];
        int a=id_root[pp[fY].first][pp[fY].second];
        val+=a*sz_all*mxD+b*mxD+dist-1;
      }
      else{
        dist-=mxD;
        val+=sz_root*sz_all*mxD;
        int a=id_root[pp[fX].first][pp[fX].second];
        int b=id_root[pp[fY].first][pp[fY].second];
        val+=a*sz_root*mxD+b*mxD+dist-1;
      }
    }
    val+=2;
    string res(L+1,'0');
    for(int i=0;i<=L;i++) if(val>>i&1) res[i]='1';
    while(res.back()=='0') res.pop_back();
    if(res.back()=='1') res.pop_back();
    return res;
  }
}
void Init(int _N, std::vector<int> U, std::vector<int> V) {
  Ali::Init(_N,U,V);
}
std::string SendA(std::string S) {
  return Ali::SendA(S);
}
#include "Benjamin.h"
#include <bits/stdc++.h>
using namespace std;
namespace Benjamin{
  const int K = 7;
  const int L = 24;
  const int LG = 10;
  const int mxD = 50000;
  const int sz_root = 21;
  const int sz_all = 290;
  // List of Small Tree
  const int sz7 = 5;
  vector<string> T7 = {
    "000011100111", // [0]
    "000011011011", // [1]
    "000001101111", // [2]
    "000110110011", // [3]
    "000011011101"  // [4]
  };
  const int sz6 = 11;
  vector<string> T6 = {
    "0001100111",  // Group 0
    "0001011011",  // Group 1
    "0000111011",  // Group 1
    "0000011111",  // Group 2
    "0000101111",  // Group 2
    "0001101101",  // Group 3
    "0010110011",  // Group 3
    "0001110011",  // Group 3
    "0000110111",  // Group 4
    "0000111101",  // Group 4
    "0001011101"   // Group 4
  };
  vector<int> group = {0,1,1,2,2,3,3,3,4,4,4};
  int get_hash(string hash){
    for(int i=0;i<sz6;i++) if(T6[i]==hash) return i;
    assert(false);
    return -1;
  }
  map<vector<int>,int> root_tree,all_tree;
  int id_all[sz7+5][sz6+5][2*K+5];
  int id_root[sz7+5][sz6+5];
  bool init=false;
  void INIT(){
    if(init) return;
    //cout << "B_Init" << endl;
    memset(id_all,-1,sizeof(id_all));
    memset(id_root,-1,sizeof(id_root));
    assert(root_tree.empty() && all_tree.empty());
    init=true;
    
    for(int b=0;b<sz6;b++) for(int a=group[b];a<sz7;a++){
      //cout << "Start " << a << ' ' << b << endl;
      string cur="0"+T7[a]+"10"+T6[b]+"1";
      vector<int> deg(2*K);
      vector<vector<int>> edge(2*K);
      int T=0;
      vector<int> x;
      x.push_back(0);
      vector<pair<int,int>> e;
      for(char c:cur){
        if(c=='0'){
          e.push_back({x.back(),++T});
          x.push_back(T);
        }
        else x.pop_back();
      }
      for(auto [u,v]:e){
        deg[u]++,deg[v]++;
        edge[u].push_back(v);
      }
      T=0;
      vector<int> c(2*K,-1);
      queue<int> q;q.push(0);
      while(!q.empty()){
        int u=q.front();q.pop();
        c[u]=T++;
        for(int v:edge[u]) q.push(v);
      }
      for(auto [u,v]:e) edge[v].push_back(u);
      vector<bool> ex(2*K);
      if(a==1) ex[3]=true;
      else if(a==2) ex[4]=true;
      else if(a==3) ex[2]=true;
      else if(a==4) ex[1]=ex[3]=true;
      for(int i=0;i<2*K;i++){
        if(deg[i]==3 && !ex[i]) continue;
        vector<int> d(2*K,0);
        function<void(int,int)> dfs = [&](int u,int p){
          for(int v:edge[u]) if(v!=p) d[c[v]]=d[c[u]]+1,dfs(v,u);
        };
        dfs(i,-1);
        if(all_tree.find(d)==all_tree.end()) all_tree[d]=(int)all_tree.size();
        id_all[a][b][c[i]]=all_tree[d];
        if(i==0 && root_tree.find(d)==root_tree.end()) root_tree[d]=(int)root_tree.size();
        if(i==0) id_root[a][b]=root_tree[d];
      }
      //cout << "End " << a << ' ' << b << endl;
    }
    assert(sz_root==(int)root_tree.size());
    assert(sz_all==(int)all_tree.size());
    //cout << (int)all_tree.size() << ' ' << (int)root_tree.size() << '\n';
    
  }
  int cX,cY;
  string SendB(int N,int X,int Y){
    //cout << "Start SendB" << endl;
    //cout << "End Init" << endl;
    int fX=X/(2*K),fY=Y/(2*K);
    cX=X%(2*K),cY=Y%(2*K);
    if(fX>fY) swap(fX,fY),swap(cX,cY);
    string s(2*LG,'0');
    for(int i=0;i<LG;i++) s[i]=char('0'+(fX>>i&1)),s[LG+i]=char('0'+(fY>>i&1));
    //cout << "End SendB" << endl;
    return s;
  }
  int Answer(string S) {
    INIT();
    int val=(1<<(int)S.length());
    for(int i=0;i<(int)S.length();i++) val+=(S[i]-'0')<<i;
    val-=2;
    if(val<sz7*sz6){
      int b=val%sz6;val/=sz6;
      int a=val;
  
      string cur="0"+T7[a]+"10"+T6[b]+"1";
      
      vector<vector<int>> edge(2*K);
  
      int T=0;
      vector<int> x;
      x.push_back(0);
      vector<pair<int,int>> e;
      
      for(char c:cur){
        if(c=='0'){
          e.push_back({x.back(),++T});
          x.push_back(T);
        }
        else x.pop_back();
      }
      
      vector<int> c(2*K,-1);
      for(auto [u,v]:e) edge[u].push_back(v);
  
      queue<int> q;q.push(0);
      while(!q.empty()){
        int u=q.front();q.pop();
        c[u]=T++;
        for(int v:edge[u]) q.push(v);
      }
  
      int X=-1,Y=-1;
      for(int i=0;i<2*K;i++) if(c[i]==cX){X=i;break;}
      for(int i=0;i<2*K;i++) if(c[i]==cY){Y=i;break;}
  
      for(auto [u,v]:e) edge[v].push_back(u);
  
      function<int(int,int)> dfs = [&](int u,int p){
        if(u==Y) return 0;
        for(int v:edge[u]) if(v!=p){
          int val=dfs(v,u);
          if(val!=-1) return val+1;
        }
        return -1;
      };
  
      return dfs(X,-1);
    } 
    else{
      val-=sz7*sz6;
      if(val<sz_root*sz_all*mxD){
        int dist=val%mxD+1;val/=mxD;
        int b=val%sz_all;val/=sz_all;
        int a=val;
  
        for(auto &[d,id]:root_tree) if(id==a) dist+=d[cY];
        for(auto &[d,id]:all_tree) if(id==b) dist+=d[cX];
        return dist;
      }
      else{
        val-=sz_root*sz_all*mxD;
        int dist=val%mxD+mxD+1;val/=mxD;
        int b=val%sz_root;val/=sz_root;
        int a=val;
        for(auto &[d,id]:root_tree){
          if(id==b) dist+=d[cY];
          if(id==a) dist+=d[cX];
        }
        return dist;
      }
    }
  }
  
}
std::string SendB(int N, int X, int Y) {
  return Benjamin::SendB(N,X,Y);
}
int Answer(string S) {
  return Benjamin::Answer(S);
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |