제출 #1332882

#제출 시각아이디문제언어결과실행 시간메모리
1332882SmuggingSpunShortcut (IOI16_shortcut)C++20
100 / 100
1415 ms39556 KiB
#include "shortcut.h"
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
template<class T>void minimize(T& a, T b){
  if(a > b){
    a = b;
  }
}
template<class T>void maximize(T& a, T b){
  if(a < b){
    a = b;
  }
}
const int lim = 1e6 + 5;
int n, c, l[lim], d[lim];
ll f[lim];
namespace sub12{
  const int lim = 205;
  ll dist[lim][lim];
  void add_edge(int u, int v, int w){
    dist[u][v] = dist[v][u] = w;
  }
  ll solve(){
    memset(dist, 0x0f, sizeof(dist));
    for(int i = 1; i < n; i++){
      add_edge(i, i + 1, l[i]);
    }
    int N = n + 1;
    for(int i = 1; i <= n; i++){
      if(d[i] > 0){
        add_edge(i, N++, d[i]);
      }
    }
    for(int i = 1; i < N; i++){
      dist[i][i] = 0;
    }
    for(int k = 1; k < N; k++){
      for(int u = 1; u < N; u++){
        for(int v = 1; v < N; v++){
          minimize(dist[u][v], dist[u][k] + dist[k][v]);
        }
      }
    }
    ll ans = INF;
    for(int i = 1; i < n; i++){
      for(int j = i + 1; j <= n; j++){
        ll diam = 0;
        for(int u = 1; u < N; u++){
          for(int v = u + 1; v < N; v++){
            maximize(diam, min(dist[u][v], min(dist[u][i] + dist[j][v], dist[u][j] + dist[i][v]) + c));
          }
        }
        minimize(ans, diam);
      }
    }
    return ans;
  }
}
namespace sub34{
  const int lim = 505;
  ll min_fd[lim][lim], max_du[lim][lim];
  ll solve(){
    memset(min_fd, 0x0f, sizeof(min_fd));
    f[1] = 0;
    for(int i = 1; i < n; i++){
      f[i + 1] = f[i] + l[i];
    }
    for(int i = 1; i <= n; i++){
      min_fd[i][i] = f[i] - d[i];
    }
    for(int l = n - 1; l > 0; l--){
      for(int r = l + 1; r <= n; r++){
        min_fd[l][r] = min(min_fd[l + 1][r], min_fd[l][l]);
      }
    }
    memset(max_du, -0x0f, sizeof(max_du));
    for(int u = 1; u <= n; u++){
      for(int i = 1; i <= u; i++){
        max_du[u][i] = max(max_du[u][i - 1], f[u] - f[i] + d[i]);
      }
      for(int i = u + 1; i <= n; i++){
        max_du[u][i] = max(max_du[u][i - 1], f[i] - f[u] + d[i]);
      }
    }
    ll ans = INF;
    for(int u = 1, max_d = *max_element(d + 1, d + n + 1); u < n; u++){
      for(int v = u + 1; v <= n; v++){
        ll diam = max_d;
        for(int j = 2; j < u; j++){
          maximize(diam, f[j] + d[j] - min_fd[1][j - 1]);
        }
        for(int j = u, i = u; j <= v; j++){
          while(i < j && f[j] - f[i] > (f[i] - f[u]) + (f[v] - f[j]) + c){
            i++;
          }
          if(i > u){
            maximize(diam, max(f[j] + d[j] - min_fd[i][j - 1], f[v] - f[j] + d[j] + c + max_du[u][i - 1]));
          }
          else{
            maximize(diam, f[j] + d[j] - min_fd[1][j - 1]);
          }
        }
        int pi = -1;
        for(int i = v; i >= u; i--){
          if(f[i] - f[u] + c < f[v] - f[i]){
            pi = i;
            break;
          }
        }
        for(int j = v + 1; j <= n; j++){
          if(pi == -1){
            maximize(diam, f[j] + d[j] - min_fd[1][j - 1]);
          }
          else{
            maximize(diam, max(f[j] + d[j] - min_fd[pi + 1][j - 1], f[j] - f[v] + d[j] + c + max_du[u][pi]));
          }
        }
        minimize(ans, diam);
      }
    }
    return ans;
  }
}
namespace sub5{
  const int lim = 3e3 + 5;
  bool check(ll k){
    ll x1 = -INF, x2 = INF, y1 = -INF, y2 = INF;
    for(int i = 1; i < n; i++){
      for(int j = i + 1; j <= n; j++){
        if(f[j] - f[i] + d[i] + d[j] > k){
          ll delta = k - d[i] - d[j] - c, px = f[i] + f[j], py = f[i] - f[j];
          if(delta < 0){
            return false;
          }
          maximize(x1, px - delta);
          minimize(x2, px + delta);
          maximize(y1, py - delta);
          minimize(y2, py + delta);
        }
      }
    }
    for(int i = 1; i < n; i++){
      for(int j = i + 1; j <= n; j++){
        ll px = f[i] + f[j], py = f[i] - f[j];
        if(x1 <= px && x2 >= px && y1 <= py && y2 >= py){
          return true;
        }
      }
    }
    return false;
  }
  ll solve(){
    ll low = f[1] = 0, high = INF, ans = INF;
    for(int i = 1; i < n; i++){
      f[i + 1] = f[i] + l[i];
    }
    while(low <= high){
      ll mid = (low + high) >> 1LL;
      if(check(mid)){
        high = (ans = mid) - 1;
      }
      else{
        low = mid + 1;
      }
    }
    return ans;
  }
}
namespace sub678{
  int pi[lim], pj[lim];
  pair<ll, ll>overlap(pair<ll, ll>r1, pair<ll, ll>r2){
    return make_pair(max(r1.first, r2.first), min(r1.second, r2.second));
  }
  bool check(ll k){
    ll x1 = -INF, x2 = INF, y1 = -INF, y2 = INF, kc = k - c;
    pair<int, int>max_plus = make_pair(0, 0), min_minus = make_pair(0, 0);
    for(int ptj = 0, pti = 0; ptj < n; ptj++){
      int j = pj[ptj];
      while(pti < n){
        int i = pi[pti];
        if(f[j] + d[j] - f[i] + d[i] <= k){
          break;
        }
        pti++;
        if(max_plus.first == 0){
          max_plus.first = min_minus.first = i;
        }
        else{
          ll val = f[i] + d[i];
          if(val >= f[max_plus.first] + d[max_plus.first]){
            max_plus.second = max_plus.first;
            max_plus.first = i;
          }
          else if(max_plus.second == 0 || val > f[max_plus.second] + d[max_plus.second]){
            max_plus.second = i;
          }
          if((val = f[i] - d[i]) <= f[min_minus.first] - d[min_minus.first]){
            min_minus.second = min_minus.first;
            min_minus.first = i;
          }
          else if(min_minus.second == 0 || val < f[min_minus.second] - d[min_minus.second]){
            min_minus.second = i;
          }
        }
      }
      if(pti > 0){
        if(kc < 0){
          return false;
        }
        int i = max_plus.first == j ? max_plus.second : max_plus.first;
        if(i != 0){
          ll max_plus = f[i] + d[i];
          maximize(x1, max_plus + f[j] + d[j] - kc);
          minimize(y2, f[j] - d[j] - max_plus + kc);
        }
        if((i = min_minus.first == j ? min_minus.second : min_minus.first) != 0){
          ll min_minus = f[i] - d[i];
          minimize(x2, min_minus + f[j] - d[j] + kc);
          maximize(y1, f[j] + d[j] - min_minus - kc);
        }
      }
    }
    if(x1 > x2 || y1 > y2){
      return false;
    }
    for(int j = 1, ix1 = n, ix2 = n, iy1 = 1, iy2 = 1; j <= n; j++){
      while(ix1 > 0 && f[j] + f[ix1] >= x1){
        ix1--;
      }
      while(ix2 > 0 && f[j] + f[ix2] > x2){
        ix2--;
      }
      while(iy1 <= n && f[j] - f[iy1] >= y1){
        iy1++;
      }
      while(iy2 <= n && f[j] - f[iy2] > y2){
        iy2++;
      }
      pair<ll, ll>rall = overlap(overlap(make_pair(1, j - 1), make_pair(ix1 + 1, ix2)), overlap(make_pair(1, iy1 - 1), make_pair(iy2, j)));
      if(rall.first <= rall.second){
        return true;
      }
    }
    return false;
  }
  ll solve(){
    for(int i = f[1] = 0; i < n; i++){
      pi[i] = pj[i] = i + 1;
    }
    for(int i = 1; i < n; i++){
      f[i + 1] = f[i] + l[i];
    }
    sort(pi, pi + n, [&] (int i, int j){
      return f[i] - d[i] < f[j] - d[j];
    });
    sort(pj, pj + n, [&] (int i, int j){
      return f[i] + d[i] < f[j] + d[j];
    });
    ll low = *max_element(d + 1, d + n + 1), high = INF, ans = INF;
    while(low <= high){
      ll mid = (low + high) >> 1LL;
      if(check(mid)){
        high = (ans = mid) - 1;
      }
      else{
        low = mid + 1;
      }
    }
    return ans;
  }
}
ll find_shortcut(int _n, vector<int>_l, vector<int>_d, int _c){
  c = _c;
  for(int i = n = _n; i > 0; i--){
    l[i] = _l[i - 1];
    d[i] = _d[i - 1];
  }
  if(n <= 100){
    return sub12::solve();
  }
  if(n <= 500){
    return sub34::solve();
  }
  if(n <= 3000){
    return sub5::solve();
  }
  return sub678::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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...