제출 #423865

#제출 시각아이디문제언어결과실행 시간메모리
423865KoDShortcut (IOI16_shortcut)C++17
97 / 100
2111 ms368196 KiB
#include <bits/stdc++.h> #include "shortcut.h" template <class T> using Vec = std::vector<T>; using ll = long long; constexpr ll INF = std::numeric_limits<ll>::max() / 2; template <class T> void setmin(T& lhs, const T& rhs) { if (lhs > rhs) { lhs = rhs; } } template <class T> void setmax(T& lhs, const T& rhs) { if (lhs < rhs) { lhs = rhs; } } struct RMQ { Vec<Vec<ll>> table; RMQ(const Vec<ll>& vec) { const int n = (int) vec.size(); const int h = 32 - __builtin_clz(n); table.resize(h); table[0] = vec; for (int k = 0; k < h - 1; ++k) { const int len = n - (1 << (k + 1)) + 1; table[k + 1].resize(len); for (int i = 0; i < len; ++i) { table[k + 1][i] = std::min(table[k][i], table[k][i + (1 << k)]); } } } ll fold(const int l, const int r) { if (l >= r) return INF; const int h = 31 - __builtin_clz(r - l); return std::min(table[h][l], table[h][r - (1 << h)]); } }; ll find_shortcut(int n, Vec<int> l, Vec<int> d, int c) { Vec<ll> x(n), xd_dif(n), xd_sum(n); for (int i = 1; i < n; ++i) { x[i] = x[i - 1] + l[i - 1]; } for (int i = 0; i < n; ++i) { xd_dif[i] = d[i] - x[i]; xd_sum[i] = d[i] + x[i]; } Vec<ll> base1(n), base2(n); Vec<int> idx(n), ord(n); std::iota(ord.begin(), ord.end(), 0); std::sort(ord.begin(), ord.end(), [&](const int i, const int j) { return xd_dif[i] < xd_dif[j]; }); Vec<ll> cmp(n); for (int i = 0; i < n; ++i) { idx[ord[i]] = i; cmp[i] = xd_dif[ord[i]]; } for (int i = 0; i < n; ++i) { base1[idx[i]] = -xd_dif[i]; base2[idx[i]] = -xd_sum[i]; } RMQ min1(base1), min2(base2); std::sort(ord.begin(), ord.end(), [&](const int i, const int j) { return xd_sum[i] > xd_sum[j]; }); const auto check = [&](const ll threshold) -> bool { const ll W = threshold - c; ll sum_min = -INF, sum_max = INF; ll dif_min = -INF, dif_max = INF; int pos = 0; for (const int i: ord) { while (pos < n and cmp[pos] <= threshold - xd_sum[i]) pos += 1; const ll a = [&] { if (idx[i] < pos) return min1.fold(pos, n); else return std::min(min1.fold(pos, idx[i]), min1.fold(idx[i] + 1, n)); }(); const ll b = [&] { if (idx[i] < pos) return min2.fold(pos, n); else return std::min(min2.fold(pos, idx[i]), min2.fold(idx[i] + 1, n)); }(); if (a != INF and b != INF) { setmin(sum_max, a - xd_dif[i] + W); setmax(sum_min, -b + xd_sum[i] - W); setmin(dif_max, b - xd_dif[i] + W); setmax(dif_min, -a + xd_sum[i] - W); } } if (sum_min > sum_max or dif_min > dif_max) { return false; } int s = n, t = 0, u = n - 1, v = 0; for (int i = 0; i < n; ++i) { while (s > 0 and x[s - 1] >= sum_min - x[i]) s -= 1; while (t < n and x[t] < dif_min + x[i]) t += 1; while (u >= 0 and x[u] > sum_max - x[i]) u -= 1; while (v + 1 < n and x[v + 1] <= dif_max + x[i]) v += 1; if (std::max({s, t, i + 1}) <= std::min(u, v)) { return true; } } return false; }; ll ok = 1000000000ll * (999999ll + 2ll), ng = std::max(0, *std::max_element(d.begin(), d.end()) - 1); while (ok - ng > 1) { const auto md = (ok + ng) / 2; (check(md) ? ok : ng) = md; } return ok; }
#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...