Submission #1035619

#TimeUsernameProblemLanguageResultExecution timeMemory
1035619LudisseyHighway Tolls (IOI18_highway)C++14
51 / 100
453 ms262144 KiB
#include "highway.h"
#include <bits/stdc++.h>
#define sz(a) (int)a.size()
#define int long long
#define all(x) (x).begin(), (x).end()
using namespace std;
vector<int> depth;
vector<pair<int,int>> parent;
vector<int> sz;
vector<vector<pair<int,int>>> child;
vector<vector<pair<int,int>>> neigh;
vector<vector<pair<int,int>>> neigh2;
vector<signed> aska;
int S=-1;
int M,N;
int shortest;
int totCount=0;
int prevP=0;
int getSIZE(int x){
    sz[x]=1;
    for (auto u : child[x])
    {
        sz[x]+=getSIZE(u.first);
    }
    return sz[x];
}
int find_centroid(int _x){
    int x = _x;
    int sizeT=sz[_x];
    while (true) {
        int c = -1;
        for (int i = 0; i < sz(child[x]); i++) {
            if (sz[child[x][i].first]>sizeT/2) c = child[x][i].first;
        }
        //if (sz[x]-1>sizeT/2&&parent[x].first!=-1) c = parent[x].first;
        if (c!=-1) x = c; 
        else break;
    }
    return x;
}
 
void reroot(int R){
    child.clear();
    parent.clear();
    child.resize(N);
    parent.resize(N);
    queue<pair<int,int>> q;
    q.push({R,-1});
    parent[R]={-1,-1};
    while(!q.empty()){
        int x=q.front().first,p=q.front().second; q.pop();
        for (auto u : neigh2[x])
        {
            if(u.first==p||u.first==-1) continue;
            child[x].push_back(u);
            parent[u.first]={x,u.second};
            q.push({u.first,x});
        }
    }
}
 
void colorSubtree(int x){
    aska[parent[x].second]=1;
    for (auto u : child[x])
    {
        colorSubtree(u.first);
    }
}
 
int findTree(int x){
    int l=0, r=sz(child[x])-1;
    aska.resize(M);
    int ans=-1;
    while(l<=r){
        for (int i = 0; i < M; i++) aska[i]=0;
        int mid=(l+r)/2;
        for (int i = 0; i <= mid; i++)
        {
            colorSubtree(child[x][i].first);
        }
        totCount++;
        if(ask(aska)>shortest){
            ans=mid;
            r=mid-1;
        }else{
            l=mid+1;
        }
        
    }
    if(ans<0) {
        for (int i = 0; i < M; i++) aska[i]=0;
        if(parent[x].first>-1) {
            aska[parent[x].second]=1;
            if(ask(aska)>shortest){
                S=x;
                return S;
            }
            for (int i = 0; i < sz(neigh2[parent[x].first]); i++)
            {
                if(neigh2[parent[x].first][i].first==x){
                    neigh2[parent[x].first][i].first=-1;
                }
            }
            return prevP;
        }
        S=x;
        return S;
    }
    else{
        for (int i = 0; i < sz(neigh2[child[x][ans].first]); i++)
        {
            if(neigh2[child[x][ans].first][i].first==x){
                neigh2[child[x][ans].first][i].first=-1;
            }
        }
        return child[x][ans].first;
    }
}
 
void find_pair(signed n, std::vector<signed> U, std::vector<signed> V, signed A, signed B){
    M=sz(U);
    N=n;
    neigh.resize(N);
    neigh2.resize(N);
    child.resize(N);
    sz.resize(N);
    depth.resize(N);
    parent.resize(N);
    vector<signed> ep(M,0);
    shortest=ask(ep);
    int initDist=shortest/A;
    totCount=0;
    for (int i = 0; i < M; i++)
    {
        neigh[U[i]].push_back({V[i],i});
        neigh[V[i]].push_back({U[i],i});
        neigh2[U[i]].push_back({V[i],i});
        neigh2[V[i]].push_back({U[i],i});
    }
    int c=0;
    reroot(0);
    while(S<0){
        //cerr<<c<<"\n";
        prevP=c;
        getSIZE(c);
        int _c=find_centroid(c);
        _c=findTree(_c);
        c=_c;
        reroot(c);
        if(sz(child[c])==0) {
            S=c;
        }
    }
 
    vector<int> possible;
    queue<pair<int,int>> q;
    q.push({S,-1});
    child.clear();
    parent.clear();
    depth.clear();
    neigh.resize(N);
    child.resize(N);
    depth.resize(N);
    parent.resize(N);
    depth[S]=0;
    while(!q.empty()){
        int x=q.front().first,p=q.front().second; q.pop();
        if(depth[x]==initDist) possible.push_back(x);
        for (auto u : neigh[x])
        {
            if(u.first==p) continue;
            child[x].push_back(u);
            depth[u.first]=depth[x]+1;
            parent[u.first]={x,u.second};
            q.push({u.first,x});
        }
    }
    int l=0; int r=sz(possible)-1;
    while(l<r){
        int mid=(l+r)/2;
        vector<signed> w(M,0);
        for (int i = l; i <= mid; i++) { w[parent[possible[i]].second]=1; }
        if(ask(w)>shortest){
            r=mid;
        }else{
            l=mid+1;
        }
    }
    answer(S,(int)possible[l]);
}
#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...