This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// M
#include<bits/stdc++.h>
#include "walk.h"
#define lc (id << 1)
#define rc (lc ^ 1)
#define md ((l + r) >> 1)
#define pb push_back
using namespace std;
typedef long long ll;
const int N = 100005, MXM = N * 5, MXN = MXM * 2;
int n, ts, A[N], MX[N * 4], Lid[MXM], Rid[MXM];
vector < int > S[N], E[N], V[N], ID[N];
vector < pair < int , ll > > Adj[MXN];
ll D[MXN];
inline void AddEdge(int v, int u, ll w)
{
assert(w >= 0);
Adj[v].pb({u, w});
Adj[u].pb({v, w});
}
void Build(int id = 1, int l = 0, int r = n)
{
if (r - l < 2)
return void(MX[id] = A[l]);
Build(lc, l, md);
Build(rc, md, r);
MX[id] = max(MX[lc], MX[rc]);
}
int GetFirst(int i, int val, int id = 1, int l = 0, int r = n)
{
if (r <= i || MX[id] < val)
return -1;
if (r - l < 2)
return l;
int rt = GetFirst(i, val, lc, l, md);
if (rt != -1)
return rt;
return GetFirst(i, val, rc, md, r);
}
int GetLast(int i, int val, int id = 1, int l = 0, int r = n)
{
if (i < l || MX[id] < val)
return -1;
if (r - l < 2)
return l;
int rt = GetLast(i, val, rc, md, r);
if (rt != -1)
return rt;
return GetLast(i, val, lc, l, md);
}
ll min_distance(vector < int > X, vector < int > H, vector < int > L, vector < int > R, vector < int > Y, int st, int fn)
{
n = (int)X.size();
for (int i = 0; i < n; i ++)
A[i] = H[i];
Build();
if (st > fn)
swap(st, fn);
if (st == fn)
return 0LL;
for (int i = 0; i < (int)L.size(); i ++)
if (L[i] < st && st < R[i])
{
int l = GetLast(st, Y[i]);
int r = GetFirst(st, Y[i]);
assert(l != -1 && r != -1);
assert(l >= L[i] && r <= R[i]);
if (L[i] < l)
L.pb(L[i]), R.pb(l), Y.pb(Y[i]);
if (r < R[i])
L.pb(r), R.pb(R[i]), Y.pb(Y[i]);
L[i] = l; R[i] = r;
}
for (int i = 0; i < (int)L.size(); i ++)
if (L[i] == R[i])
{
swap(L[i], L.back()); L.pop_back();
swap(R[i], R.back()); R.pop_back();
swap(Y[i], Y.back()); Y.pop_back();
i --;
}
for (int i = 0; i < (int)L.size(); i ++)
if (L[i] < fn && fn < R[i])
{
int l = GetLast(fn, Y[i]);
int r = GetFirst(fn, Y[i]);
assert(l != -1 && r != -1);
assert(l >= L[i] && r <= R[i]);
if (L[i] < l)
L.pb(L[i]), R.pb(l), Y.pb(Y[i]);
if (r < R[i])
L.pb(r), R.pb(R[i]), Y.pb(Y[i]);
L[i] = l; R[i] = r;
}
for (int i = 0; i < (int)L.size(); i ++)
if (L[i] == R[i])
{
swap(L[i], L.back()); L.pop_back();
swap(R[i], R.back()); R.pop_back();
swap(Y[i], Y.back()); Y.pop_back();
i --;
}
for (int i = 0; i < (int)L.size(); i ++)
S[L[i]].pb(i), E[R[i]].pb(i);
for (int i = 0; i < n; i ++)
{
if (i == st || i == fn)
V[i].pb(0);
for (int j : S[i])
V[i].pb(Y[j]);
for (int j : E[i])
V[i].pb(Y[j]);
sort(V[i].begin(), V[i].end());
V[i].resize(unique(V[i].begin(), V[i].end()) - V[i].begin());
for (int j : V[i])
ID[i].pb(ts ++);
}
for (int i = 0; i < (int)L.size(); i ++)
{
Lid[i] = ID[L[i]][(int)(lower_bound(V[L[i]].begin(), V[L[i]].end(), Y[i]) - V[L[i]].begin())];
Rid[i] = ID[R[i]][(int)(lower_bound(V[R[i]].begin(), V[R[i]].end(), Y[i]) - V[R[i]].begin())];
}
set < pair < int , int > > ST;
for (int i = 0; i < n; i ++)
{
for (int j : E[i])
ST.erase({Y[j], j});
for (int j = 1; j < (int)V[i].size(); j ++)
AddEdge(ID[i][j - 1], ID[i][j], V[i][j] - V[i][j - 1]);
for (int j = 0; j < (int)V[i].size(); j ++)
{
auto it = ST.lower_bound({V[i][j], -1});
if (it != ST.begin())
{
it --;
assert(it->first < V[i][j]);
AddEdge(ts, ID[i][j], V[i][j] - it->first);
AddEdge(Lid[it->second], ts, X[i] - X[L[it->second]]);
Lid[it->second] = ts;
L[it->second] = i;
ts ++; it ++;
}
if (it != ST.end() && it->first <= H[i])
{
assert(it->first >= V[i][j]);
AddEdge(ts, ID[i][j], it->first - V[i][j]);
AddEdge(Lid[it->second], ts, X[i] - X[L[it->second]]);
Lid[it->second] = ts;
L[it->second] = i;
ts ++;
}
}
for (int j : S[i])
ST.insert({Y[j], j});
}
for (int i = 0; i < (int)L.size(); i ++)
AddEdge(Lid[i], Rid[i], X[R[i]] - X[L[i]]);
priority_queue < pair < ll , int > > Pq;
memset(D, 63, sizeof(D));
D[ID[st][0]] = 0;
Pq.push({0, ID[st][0]});
while (Pq.size())
{
ll d = -Pq.top().first;
int v = Pq.top().second;
Pq.pop();
if (v == ID[fn][0])
return d;
if (d > D[v])
continue;
for (auto u : Adj[v])
if (D[u.first] > D[v] + u.second)
D[u.first] = D[v] + u.second, Pq.push({-D[u.first], u.first});
}
return -1LL;
}
Compilation message (stderr)
walk.cpp: In function 'll min_distance(std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, int, int)':
walk.cpp:117:26: warning: unused variable 'j' [-Wunused-variable]
117 | for (int j : V[i])
| ^
# | 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... |