Submission #733383

#TimeUsernameProblemLanguageResultExecution timeMemory
733383tch1cherinRobot (JOI21_ho_t4)C++17
0 / 100
595 ms153456 KiB
#include <bits/stdc++.h> using namespace std; struct segment_tree { int lx, rx; long long min_value, push; int unused; segment_tree* left = nullptr; segment_tree* right = nullptr; segment_tree(int _lx, int _rx) : lx(_lx), rx(_rx) { min_value = push = LLONG_MAX; unused = 0; } void apply(long long v) { min_value = min(min_value, v); push = min(push, v); } void propagate() { if (push == LLONG_MAX) { return; } if (left) { left->apply(push); } if (right) { right->apply(push); } push = LLONG_MAX; } void pull() { min_value = push = LLONG_MAX; unused = 0; if (left) { if (left->unused > 0) { min_value = min(min_value, left->min_value); unused += left->unused; } } if (right) { if (right->unused > 0) { min_value = min(min_value, right->min_value); unused += right->unused; } } } void Left() { left = (left ? left : new segment_tree(lx, (lx + rx) / 2)); } void Right() { right = (right ? right : new segment_tree((lx + rx) / 2, rx)); } void update(int l, int r, long long v) { if (lx >= l && rx <= r) { apply(v); } else { propagate(); int mid = (lx + rx) / 2; if (l < mid) { Left(); left->update(l, r, v); } if (r > mid) { Right(); right->update(l, r, v); } pull(); } } void modify(int i, long long v, bool is_unused) { if (rx - lx == 1) { if (!is_unused) { unused = 0; min_value = push = LLONG_MAX; } else { unused = 1; min_value = push = v; } } else { propagate(); int mid = (lx + rx) / 2; if (i < mid) { Left(); left->modify(i, v, is_unused); } else { Right(); right->modify(i, v, is_unused); } pull(); } } pair<long long, int> get_min() { if (unused == 0) { return {LLONG_MAX, -1}; } else if (!left && !right) { return {min_value, lx}; } else { propagate(); bool left_good = left && left->min_value == min_value && left->unused > 0; bool right_good = right && right->min_value == min_value && right->unused > 0; if (left_good) { return left->get_min(); } else if (right_good) { return right->get_min(); } else { if (left && (left->min_value != min_value || left->unused == 0)) { return {min_value, (lx + rx) / 2}; } else { return {min_value, lx}; } } } } }; template <typename T> using min_heap = priority_queue<T, vector<T>, greater<T>>; void solve() { int n, m; cin >> n >> m; vector<map<int, long long>> sum(n), dist(n); vector<map<int, vector<pair<int, int>>>> g(n); vector<segment_tree> st(n, segment_tree(0, 2 << __lg(m))); for (int i = 0; i < m; i++) { int a, b, c, p; cin >> a >> b >> c >> p; a--, b--; g[a][c].emplace_back(b, p); g[b][c].emplace_back(a, p); sum[a][c] += p; sum[b][c] += p; } min_heap<tuple<long long, int, int>> q; for (int i = 1; i < n; i++) { for (auto [color, value] : sum[i]) { st[i].modify(color, LLONG_MAX, true); } } for (auto [color, value] : sum[0]) { q.emplace(0, 0, color); dist[0][color] = 0; } set<pair<int, int>> used; long long ans = LLONG_MAX; while (!q.empty()) { auto [d, u, nxt] = q.top(); q.pop(); if (used.count({u, nxt})) { continue; } used.emplace(u, nxt); st[u].modify(nxt, dist[u][nxt], false); auto [MinValue, Pos] = st[u].get_min(); if (Pos != -1) { dist[u][Pos] = MinValue; q.emplace(MinValue, u, Pos); } auto S = sum[u][nxt], D = dist[u][nxt]; for (auto [v, p] : g[u][nxt]) { if (v == n - 1) { ans = min({ans, D + p, D + S - p}); } st[v].update(0, 2 << __lg(m), D + p); if (nxt > 0) { st[v].update(0, nxt, D + S - p); } if (nxt + 1 < (2 << __lg(m))) { st[v].update(nxt + 1, 2 << __lg(m), D + S - p); } auto [min_value, pos] = st[v].get_min(); if (pos != -1) { if (dist[v].count(pos)) { dist[v][pos] = min(dist[v][pos], min_value); } else { dist[v][pos] = min_value; } q.emplace(min_value, v, pos); } } } cout << (ans == LLONG_MAX ? -1 : ans) << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); solve(); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...