Submission #1216656

#TimeUsernameProblemLanguageResultExecution timeMemory
1216656the_coding_poohHighway Tolls (IOI18_highway)C++20
69 / 100
1541 ms39520 KiB
#include "highway.h"
#include <bits/stdc++.h>
#define uwu return

using namespace std;

#define fs first
#define sc second

#define all(x) x.begin(), x.end()

int M;

const int SIZE = 9e4 + 4;

vector <int> graph[SIZE];

long long original_dist;

map <pair<int, int>, int> edge_id;

vector <pair<int, int>> always_blocked;

bool query_edges(vector <pair<int, int>> &edges){
    vector<int> w(M, 0);
    for(auto i:edges){
        w[edge_id[i]] = 1;
    }
    for(auto i:always_blocked){
        w[edge_id[i]] = 1;
    }
    return ask(w) != original_dist;
}

bitset <SIZE> been;

int order[SIZE];

vector <int> in_edge[SIZE];

int dist[SIZE];

int cnt;

void get_BFS_DAG(int nd){
    dist[nd] = 0;
    queue <int> q;
    q.push(nd);
    been[nd] = 1;
    while (!q.empty()){
        int i = q.front();
        q.pop();
        for (auto j : graph[i]){
            if (been[j]){
                if(dist[j] == dist[i] + 1)
                    in_edge[j].push_back(i);
                continue;
            }
            been[j] = 1;
            dist[j] = dist[i] + 1;
            in_edge[j].push_back(i);
            q.push(j);
        }
    }
    uwu;
}

void get_dfs_order(int nd){
    cnt++;
    order[cnt] = nd;
    been[nd] = 1;
    for (auto i : graph[nd]){
        if(been[i] || dist[i] != dist[nd] + 1){
            continue;
        }
        get_dfs_order(i);
    }
    return;
}

int find_BFS_DAG_stuff(int nd, int pa){
    been.reset();
    memset(dist, 0x3f, sizeof(dist));
    get_BFS_DAG(nd);
    been.reset();
    cnt = 0;
    get_dfs_order(nd);
    int ret = nd;
    for (int L = 1, R = cnt, M; L != R;){
        M = (L + R + 1) / 2;
        vector <pair<int, int>> block;
        for (int i = M; i <= cnt; i++){
            for(auto j:in_edge[order[i]]){
                block.push_back({order[i], j});
            }
        }
        if(query_edges(block)){
            L = M;
        }
        else{
            R = M - 1;
        }
        ret = order[L];
    }
    return ret;
}

pair <int, int> find_split_edge(int M, int N, vector <int> &U, vector <int> &V){
    int ret = 0;
    for (int l = 0, r = M - 1, m; l != r;){
        m = (l + r + 1) / 2;
        vector <pair<int, int>> block;
        for (int i = m; i < M; i++){
            block.push_back({U[i], V[i]});
        }
        if(query_edges(block)){
            l = m;
        }
        else{
            r = m - 1;
        }
        ret = l;
    }
    set <pair<int, int>> ab;
    for (int i = ret + 1; i < M; i++){
        ab.insert({U[i], V[i]});
        ab.insert({V[i], U[i]});
        always_blocked.push_back({U[i], V[i]});
    }
    for (int i = 0; i < N; i++){
        vector <int> ng;
        for(auto j:graph[i]){
            if(ab.count({i, j}))
                continue;
            ng.push_back(j);
        }
        graph[i] = ng;
    }
    return {U[ret], V[ret]};
}

void find_pair(int N, vector<int> U, vector<int> V, int A, int B){
    M = U.size();
    vector<int> w(M);
    for (int i = 0; i < M; ++i) {
        w[i] = 0;
    }
    original_dist = ask(w);
    for (int i = 0; i < M; i++){
        edge_id[{U[i], V[i]}] = i;
        edge_id[{V[i], U[i]}] = i;
        graph[U[i]].push_back(V[i]);
        graph[V[i]].push_back(U[i]);
    }
    pair<int, int> split = find_split_edge(M, N, U, V);
    // cout << split.fs << ' ' << split.sc << '\n';
    int s = find_BFS_DAG_stuff(split.fs, split.sc), t = find_BFS_DAG_stuff(split.sc, split.fs);
    // cout << s << ' ' << t << '\n';
    answer(s, t);
    uwu;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...