Submission #1331557

#TimeUsernameProblemLanguageResultExecution timeMemory
1331557SmuggingSpunTowns (IOI15_towns)C++20
100 / 100
9 ms516 KiB
#include "towns.h"
#include<bits/stdc++.h>
using namespace std;
const int lim = 115;
const int INF = 1e9 + 36;
template<class T>void minimize(T& a, T b){
  if(a > b){
    a = b;
  }
}
template<class T>bool maximize(T& a, T b){
  if(a < b){
    a = b;
    return true;
  }
  return false;
}
int n, cache[lim][lim];
int ask(int i, int j){
  if(i > j){
    swap(i, j);
  }
  int& ans = cache[i][j];
  if(ans == -1){
    ans = getDistance(i, j);
  }
  return ans;
}
namespace sub1{
  int solve(){
    int a, b, diam = 0, ans = INF;
    for(int i = 0; i < n; i++){
      for(int j = i + 1; j < n; j++){
        if(maximize(diam, ask(i, j))){
          a = i;
          b = j;
        }
      }
    }
    for(int i = 0; i < n; i++){
      minimize(ans, max(ask(i, a), ask(i, b)) - ((ask(i, a) + ask(i, b) - diam) >> 1));
    }
    return ans;
  }
}
namespace sub2{
  int solve(){
    int a = 0, b, diam = 0, ans = INF;
    for(int i = 1, best = 0; i < n; i++){
      if(maximize(best, ask(0, i))){
        a = i;
      }
    }
    for(int i = 0; i < n; i++){
      if(maximize(diam, ask(a, i))){
        b = i;
      }
    }
    for(int i = 0; i < n; i++){
      minimize(ans, max(ask(i, a), ask(i, b)) - ((ask(i, a) + ask(i, b) - diam) >> 1));
    }
    return ans;
  }
}
namespace sub345{
  int solve(){
    int u = 0, v, diam = 0, min_rad = INF;
    for(int i = 1, best = 0; i < n; i++){
      if(maximize(best, ask(0, i))){
        u = i;
      }
    }
    for(int i = 0; i < n; i++){
      if(maximize(diam, ask(u, i))){
        v = i;
      }
    }
    auto cal_0x = [&] (int i){
      return (ask(0, i) + ask(0, u) - ask(u, i)) >> 1;
    };
    auto cal_ix = [&] (int i){
      return (ask(0, i) + ask(u, i) - ask(0, u)) >> 1;
    };
    auto cal_ux = [&] (int i){
      return (ask(u, i) + ask(0, u) - ask(0, i)) >> 1;
    };
    for(int i = 0, rod_0 = (ask(0, u) + ask(0, v) - diam) >> 1; i < n; i++){
      if(cal_0x(i) >= rod_0){
        minimize(min_rad, max(cal_ux(i), diam - cal_ux(i)));
      }
    }
    vector<int>lab(n);
    auto find_set = [&] (int i){
      while(i != lab[i]){
        i = lab[i] = lab[lab[i]];
      }
      return i;
    };
    unordered_map<int, bool>vis;
    function<bool(int)>is_balance = [&] (int d0x){
      int c0 = 0, cu = 0;
      vector<int>ver;
      for(int i = 0; i < n; i++){
        if(cal_0x(i) == d0x){
          ver.push_back(i);
        }
        else if(cal_0x(i) < d0x){
          c0++;
        }
        else{
          cu++;
        }
      }
      if(max(c0, cu) > (n >> 1)){
        return false;
      }
      if(ver.size() <= (n >> 1)){
        return true;
      }
      int candidate, cnt = 0;
      iota(lab.begin(), lab.end(), 0);
      for(int i = c0 + cu, cnt_2 = 0; i < ver.size(); i++){
        if(cnt == 0){
          candidate = ver[i];
          cnt++;
          cnt_2 = 0;
        }
        else if(cal_ix(candidate) + cal_ix(ver[i]) == ask(candidate, ver[i])){
          cnt--;
        }
        else{
          lab[ver[i]] = candidate;
          cnt++;
          if(++cnt_2 > (n >> 1)){
            return false;
          }
        }
      }
      if(cnt == 0){
        return true;
      }
      candidate = find_set(candidate);
      for(int i = cnt = 0; i < n; i++){
        if(find_set(i) == candidate){
          cnt++;
        }
      }
      for(int i = 0; i < ver.size() && cnt <= (n >> 1); i++){
        if(find_set(ver[i]) != candidate && cal_ix(find_set(ver[i])) + cal_ix(candidate) != ask(candidate, find_set(ver[i]))){
          lab[find_set(ver[i])] = candidate;
          for(int j = cnt = 0; j < n; j++){
            if(find_set(j) == candidate){
              cnt++;
            }
          }
        }
      }
      return cnt <= (n >> 1);
    };
    for(int i = 0, rod_0 = rod_0 = (ask(0, u) + ask(0, v) - diam) >> 1; i < n; i++){
      if(cal_0x(i) >= rod_0 && min_rad == max(cal_ux(i), diam - cal_ux(i))){
        int d0x = cal_0x(i);
        if(!vis[d0x]){
          vis[d0x] = true;
          if(is_balance(d0x)){
            return min_rad;
          }
        }
      }
    }
    return -min_rad;
  }
}
int hubDistance(int _n, int subtask_id){
  memset(cache, -1, sizeof(cache));
  n = _n;
  for(int i = 0; i < n; i++){
    cache[i][i] = 0;
  }
  if(subtask_id == 1){
    return sub1::solve();
  }
  if(subtask_id == 2){
    return sub2::solve();
  }
  return sub345::solve();
}
#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...