이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include "shortcut.h"
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll INF = 1e13;
void update(vector<ll> &segtree, int pos, ll val, int node, int l, int r) {
if (l == r) segtree[node] = val;
else {
int mid = (l + r) >> 1;
if (pos > mid) update(segtree, pos, val, node * 2 + 1, mid + 1, r);
else update(segtree, pos, val, node * 2, l, mid);
segtree[node] = max(segtree[node * 2], segtree[node * 2 + 1]);
}
}
ll query(vector<ll> &segtree, int a, int b, int node, int l, int r) {
if (l > b || r < a) return -INF;
if (l >= a && r <= b) return segtree[node];
int mid = (l + r) >> 1;
return max(query(segtree, a, b, node * 2, l, mid), query(segtree, a, b, node * 2 + 1, mid + 1, r));
}
ll find_shortcut(int n, vector<int> l, vector<int> d, int c) {
vector<ll> p(n, 0);
for (int i = 1; i < n; i++) p[i] = p[i - 1] + l[i - 1];
// Order the stations by their inequality stuff
vector<pair<ll, int>> iot(n);
vector<int> ord(n);
// Order by d[i] + p[i]
for (int i = 0; i < n; i++) iot[i] = {d[i] + p[i], i};
sort(iot.begin(), iot.end());
for (int i = 0; i < n; i++) ord[iot[i].second] = i;
// A segtree for each inequality
vector<ll> seg[2];
seg[0].resize(4 * n); seg[1].resize(4 * n);
// Binary search for the answer
ll lo = 0, hi = INF;
while (lo != hi) {
ll mid = (lo + hi) >> 1;
// Reset the segtrees
fill(seg[0].begin(), seg[0].end(), -INF); fill(seg[1].begin(), seg[1].end(), -INF);
vector<ll> half_plane(4, -INF);
for (int i = n - 1; ~i; i--) {
// Get the index of the first non-ignored station
int threshold = upper_bound(iot.begin(), iot.end(), make_pair(mid - d[i] + p[i], n)) - iot.begin();
// Update the half planes
ll q1 = query(seg[0], threshold, n - 1, 1, 0, n - 1);
ll q2 = query(seg[1], threshold, n - 1, 1, 0, n - 1);
half_plane[0] = max(half_plane[0], c - mid + d[i] + p[i] + q1);
half_plane[1] = max(half_plane[1], c - mid + d[i] - p[i] + q1);
half_plane[2] = max(half_plane[2], c - mid + d[i] + p[i] + q2);
half_plane[3] = max(half_plane[3], c - mid + d[i] - p[i] + q2);
// Then add station i to the segtrees
update(seg[0], ord[i], d[i] + p[i], 1, 0, n - 1);
update(seg[1], ord[i], d[i] - p[i], 1, 0, n - 1);
}
// Check that the half-planes have a common intersection
bool good = false;
// Point (x, y) is below the half-plane intersection if y < max(-x + half_plane[0], x + half_plane[1])
// Point (x, y) is above the half-plane intersection if y > min(-x - half_plane[3], x - half_plane[2])
for (int i = 0, lower = n - 1, upper = 0; i < n; i++) {
while (lower >= 0 && p[lower] >= max(-p[i] + half_plane[0], p[i] + half_plane[1]))
lower--;
while (lower + 1 < n && p[lower + 1] < max(-p[i] + half_plane[0], p[i] + half_plane[1]))
lower++;
while (upper < n && p[upper] <= min(-p[i] - half_plane[3], p[i] - half_plane[2]))
upper++;
while (upper > 0 && p[upper - 1] > min(-p[i] - half_plane[3], p[i] - half_plane[2]))
upper--;
if (upper - lower > 1) {
good = true;
break;
}
}
if (good) hi = mid;
else lo = mid + 1;
}
return lo;
}
# | 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... |