This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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);
Vec<ll> min1_cum(n + 1), min2_cum(n + 1);
min1_cum[n] = min2_cum[n] = INF;
for (int i = n - 1; i >= 0; --i) {
min1_cum[i] = std::min(min1_cum[i + 1], base1[i]);
min2_cum[i] = std::min(min2_cum[i + 1], base2[i]);
}
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_cum[pos];
else return std::min(min1.fold(pos, idx[i]), min1_cum[idx[i] + 1]);
}();
const ll b = [&] {
if (idx[i] < pos) return min2_cum[pos];
else return std::min(min2.fold(pos, idx[i]), min2_cum[idx[i] + 1]);
}();
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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |