Submission #1342849

#TimeUsernameProblemLanguageResultExecution timeMemory
1342849TahirAliyevText editor (CEOI24_editor)C++20
100 / 100
721 ms276008 KiB
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define inf 0x3F3F3F3F3F3F3F3F

signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  int x1, y1, x2, y2;
  cin >> x1 >> y1 >> x2 >> y2;
  x1--, y1--, x2--, y2--;
  int l[n];
  for (int &i : l) cin >> i;

  //2 * i  ==>  left endpoint of row i
  //2 * i + 1  ==>  right endpoint of row i
  //2 * n  ==>  starting point
  //2 * n + 1  ==>  finish point
  
  vector<array<int, 2>> adj[2 * n + 2];

  auto edge = [&](int u, int v, int w, int d) {
    adj[u].push_back({v, w});
    if (d) adj[v].push_back({u, w});
  };

  for (int i = 0; i < n; i++) {
    // From (right end) to (next row's left end)
    if (i - 1 >= 0) edge(2 * (i - 1) + 1, 2 * i, 1, 1);
    // From (left end) to (prev row's right end)
    if (i + 1 < n) edge(2 * (i + 1), 2 * i, 1, 1);
  }
  // For last row, from left end to right end
  edge(2 * (n - 1), 2 * (n - 1) + 1, l[n - 1], 1);

  // From (right end) to (prev smaller row's right end)
  {
    vector<int> st;
    for (int i = 0; i < n; i++) {
      while (!st.empty() && l[st.back()] > l[i]) st.pop_back();
      if (!st.empty()) edge(2 * i + 1, 2 * st.back() + 1, abs(i - st.back()), 0);
    }
  }
  // From (right end) to (next smaller row's right end)
  {
    vector<int> st;
    for (int i = n - 1; i >= 0; i--) {
      while (!st.empty() && l[st.back()] > l[i]) st.pop_back();
      if (!st.empty()) edge(2 * i + 1, 2 * st.back() + 1, abs(i - st.back()), 0);
    }
  }
  // from (starting point) to (left end of the same row) distance
  edge(2 * n, 2 * x1, y1, 0);

  // move the starting point up till smaller row
  for (int i = x1, mn = y1; i >= 0; i--) {
    mn = min(mn, l[i]);
    edge(2 * n, 2 * i + 1, l[i] - mn + abs(i - x1), 0);
  }
  // move the starting point down till smaller row
  for (int i = x1, mn = y1; i < n; i++) {
    mn = min(mn, l[i]);
    edge(2 * n, 2 * i + 1, l[i] - mn + abs(i - x1), 0);
  }
  edge(2 * x2, 2 * n + 1, y2, 0);
  // move the finish point up till smaller row
  for (int i = x2, mn = inf; i >= 0; i--) {
    mn = min(mn, l[i]);
    edge(2 * i + 1, 2 * n + 1, abs(y2 - mn) + abs(i - x2), 0);
  }
  // move the finish point down till smaller row
  for (int i = x2, mn = inf; i < n; i++) {
    mn = min(mn, l[i]);
    edge(2 * i + 1, 2 * n + 1, abs(y2 - mn) + abs(i - x2), 0);
  }
  // move from start to finish with manhattan distance if possible
  for (int i = min(x1, x2), mn = inf; i <= max(x1, x2); i++) {
    mn = min(mn, l[i]);
    if (i == max(x1, x2) && min(y1, y2) <= mn) edge(2 * n, 2 * n + 1, abs(x1 - x2) + abs(y1 - y2), 0);
  }

  // Shortest path djikstra
  priority_queue<array<int, 2>, vector<array<int, 2>>, greater<array<int, 2>>> pq;
  int dst[2 * n + 2];
  fill(dst, dst + 2 * n + 2, inf);
  dst[2 * n] = 0;
  pq.push({0, 2 * n});
  while (!pq.empty()) {
    auto [d, a] = pq.top();
    pq.pop();
    if (d > dst[a]) continue;
    for (auto &[v, w] : adj[a]) {
      if (dst[v] > d + w) {
        dst[v] = d + w;
        pq.push({dst[v], v});
      }
    }
  }
  cout << dst[2 * n + 1] << '\n';
}
#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...