Submission #371544

#TimeUsernameProblemLanguageResultExecution timeMemory
371544dolphingarlicShortcut (IOI16_shortcut)C++14
38 / 100
58 ms748 KiB
#include "shortcut.h" #include <bits/stdc++.h> typedef long long ll; using namespace std; const ll INF = 2e12; 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]; for (int i : {0, 1}) seg[i].resize(4 * n); // Binary search for the answer ll lo = 0, hi = INF; while (lo != hi) { ll mid = (lo + hi) >> 1; // Reset the segtrees for (int i : {0, 1}) fill(seg[i].begin(), seg[i].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 half_plane[0] = max(half_plane[0], c - mid + d[i] + p[i] + query(seg[0], threshold, n - 1, 1, 0, n - 1)); half_plane[1] = max(half_plane[1], c - mid + d[i] - p[i] + query(seg[0], threshold, n - 1, 1, 0, n - 1)); half_plane[2] = max(half_plane[2], c - mid + d[i] + p[i] + query(seg[1], threshold, n - 1, 1, 0, n - 1)); half_plane[3] = max(half_plane[3], c - mid + d[i] - p[i] + query(seg[1], threshold, n - 1, 1, 0, n - 1)); // 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 && 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 - 1) && 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 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...