Submission #1339287

#TimeUsernameProblemLanguageResultExecution timeMemory
1339287khanhphucscratchMigrations (IOI25_migrations)C++20
57.45 / 100
37 ms1748 KiB
#include "migrations.h"
#include<bits/stdc++.h>
using namespace std;
inline int getnum(int num, int b)
{
    return (num >> (2*b)) & 3;
}
vector<int> ad[10005];
int h[10005], jump[10005][20];
void update(int u, int Pu)
{
    jump[u][0] = Pu; h[u] = h[Pu] + 1;
    for(int i = 1; i <= 14; i++) jump[u][i] = jump[jump[u][i-1]][i-1];
}
int lca(int u, int v)
{
    if(u == 0 || v == 0) return 0;
    if(u == v) return u;
    if(h[u] < h[v]) swap(u, v);
    for(int i = 14; i >= 0; i--) if(h[jump[u][i]] >= h[v]) u = jump[u][i];
    if(u == v) return u;
    for(int i = 14; i >= 0; i--) if(jump[u][i] != jump[v][i]){
        u = jump[u][i]; v = jump[v][i];
    }
    return jump[u][0];
}
int dis(int u, int v)
{
    return h[u] + h[v] - 2*h[lca(u, v)];
}
pair<int, int> find_diameter(int n)
{
    for(int i = 0; i <= n; i++) ad[i].clear();
    for(int i = 1; i <= n; i++){
        int pi = jump[i][0];
        ad[pi].push_back(i); ad[i].push_back(pi);
    }
    vector<int> dis(n+1);
    fill(dis.begin(), dis.end(), 1e9); dis[0] = 0;
    queue<int> w; w.push(0);
    while(w.size() > 0){
        int u = w.front(); w.pop();
        for(int v : ad[u]) if(dis[v] > dis[u] + 1){
            dis[v] = dis[u] + 1; w.push(v);
        }
    }
    int maxnode = 0;
    for(int i = 0; i <= n; i++) if(dis[maxnode] < dis[i]) maxnode = i;
    fill(dis.begin(), dis.end(), 1e9); dis[maxnode] = 0; w.push(maxnode);
    while(w.size() > 0){
        int u = w.front(); w.pop();
        for(int v : ad[u]) if(dis[v] > dis[u] + 1){
            dis[v] = dis[u] + 1; w.push(v);
        }
    }
    int maxnode2 = 0;
    for(int i = 0; i <= n; i++) if(dis[maxnode2] < dis[i]) maxnode2 = i;
    return {maxnode, maxnode2};
}
pair<int, int> cur_diameter;
bool re_diameter = 0;
void update_diameter(int u)
{
    int cur = dis(cur_diameter.first, cur_diameter.second);
    int x = dis(cur_diameter.first, u);
    int y = dis(cur_diameter.second, u);
    if(x >= y && x > cur) cur_diameter.second = u;
    else if(y > x && y > cur) cur_diameter.first = u;
}
vector<pair<int, int>> all_cases;
void brute(int l, int r)
{
    all_cases.clear();
    all_cases.push_back(cur_diameter);
    for(int i = l; i <= r; i++){
        all_cases.push_back(make_pair(cur_diameter.first, i));
        all_cases.push_back(make_pair(i, cur_diameter.second));
    }
    for(int i = l; i <= r; i++){
        for(int j = i+1; j <= r; j++) all_cases.push_back(make_pair(i, j));
    }
    sort(all_cases.begin(), all_cases.end());
    if(re_diameter == 1){
        for(int i = l; i <= r; i++) update_diameter(i);
        if(cur_diameter.first >= l && cur_diameter.second >= l){
            if(cur_diameter.first > cur_diameter.second) swap(cur_diameter.first, cur_diameter.second);
        }
    }
}
int send_message(int n, int u, int Pu) {
    re_diameter = 1;
    n = u;
    //[0, 9973]: nothing
    //[9974, 9987]: current diameter
    //[9988, 9992]: diameter for the last 14 bits
    //[9993, 9995]: diameter for the last 5 bits
    //[9996, 9997]: diameter for the last 3 bits
    //[9998, 9999]:
    if(n <= 9973){update(n, Pu); return 0;}
    else if(n <= 9987){
        int idx = n-9974;
        if(idx == 0) cur_diameter = find_diameter(9973);
        //cerr<<"A"<<cur_diameter.first<<" "<<cur_diameter.second<<endl;
        update(n, Pu);
        if(idx <= 6) return getnum(cur_diameter.first, idx) + 1;
        else return getnum(cur_diameter.second, idx-7) + 1;
    }
    else if(n <= 9992){
        int idx = n-9988;
        if(idx == 0){
            brute(9974, 9987);
            //There should be 120 cases
            //cerr<<"A"<<all_cases.size()<<endl;
        }
        update(n, Pu);
        int p = lower_bound(all_cases.begin(), all_cases.end(), cur_diameter) - all_cases.begin();
        return getnum(p, idx) + 1;
    }
    else if(n <= 9995){
        int idx = n-9993;
        if(idx == 0){
            brute(9988, 9992);
            //There should be 21 cases
            //cerr<<"B"<<all_cases.size()<<endl;
        }
        update(n, Pu);
        int p = lower_bound(all_cases.begin(), all_cases.end(), cur_diameter) - all_cases.begin();
        return getnum(p, idx) + 1;
    }
    else if(n <= 9997){
        int idx = n-9996;
        if(idx == 0){
            brute(9993, 9995);
            //There should be 10 cases
            //cerr<<"C"<<all_cases.size()<<endl;
        }
        update(n, Pu);
        int p = lower_bound(all_cases.begin(), all_cases.end(), cur_diameter) - all_cases.begin();
        return getnum(p, idx) + 1;
    }
    else if(n == 9998){
        brute(9996, 9997);
        //There should be 6 cases
        int p = lower_bound(all_cases.begin(), all_cases.end(), cur_diameter) - all_cases.begin();
        update(n, Pu);
        return p+1; //Solve with Z <= 6
    }
    else{
        update(n, Pu);
        brute(9998, 9999);
        //There should be 6 cases
        int p = lower_bound(all_cases.begin(), all_cases.end(), cur_diameter) - all_cases.begin();
        return p+1; //Solve with Z <= 6
    }
}

int read(vector<int> &S, int l, int r)
{
    int ans = 0;
    for(int i = l; i <= r; i++){
        int idx = i-l;
        ans += ((S[i]-1) << (idx * 2));
    }
    return ans;
}
pair<int, int> longest_path(vector<int> S) {
    re_diameter = 0;
    cur_diameter = {read(S, 9974, 9980), read(S, 9981, 9987)};
    brute(9974, 9987);
    int data = read(S, 9988, 9992);
    cur_diameter = all_cases[data];

    brute(9988, 9992);
    data = read(S, 9993, 9995);
    cur_diameter = all_cases[data];

    brute(9993, 9995);
    data = read(S, 9996, 9997);
    cur_diameter = all_cases[data];

    brute(9996, 9997);
    data = read(S, 9998, 9998);
    cur_diameter = all_cases[data];

    brute(9998, 9999);
    data = read(S, 9999, 9999);
    cur_diameter = all_cases[data];
    return cur_diameter;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...