This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "walk.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> Pair;
const int Nmax = 2e6 + 5;
///13:05
vector<int> x, h, l, r, y;
vector<int> newl, newr, newy;
vector<Pair> v[Nmax];
int nr;
void add_new(int l, int r, int y)
{
    if(l == r) return;
    newl.push_back(l); newr.push_back(r); newy.push_back(y);
}
auto cmp_buildings = [](int i, int j)
{
    return h[i] > h[j];
};
auto cmp_skywalks = [] (int i, int j)
{
    return y[i] > y[j];
};
void add_edge(int x, int y, int cost)
{
    v[x].push_back({y, cost});
    v[y].push_back({x, cost});
}
void adjust(int node)
{
    newl.clear(); newr.clear(); newy.clear();
    int m = l.size();
    vector<int> s, pref, suff;
    s.resize(m);
    pref.resize(node+1);
    suff.resize(h.size()-node);
    iota(s.begin(), s.end(), 0);
    iota(pref.begin(), pref.end(), 0);
    iota(suff.begin(), suff.end(), node);
    sort(s.begin(), s.end(), cmp_skywalks);
    sort(pref.begin(), pref.end(), cmp_buildings);
    sort(suff.begin(), suff.end(), cmp_buildings);
    int id1 = 0, id2 = 0, mx = -1, mn = h.size();
    for(auto it : s)
    {
        while(id1 < pref.size() && h[pref[id1]] >= y[it])
            mx = max(mx, pref[id1]), id1++;
        while(id2 < suff.size() && h[suff[id2]] >= y[it])
            mn = min(mn, suff[id2]), id2++;
        if(l[it] < node && node < r[it])
        {
            add_new(l[it], mx, y[it]);
            add_new(mx, mn, y[it]);
            add_new(mn, r[it], y[it]);
        }
        else add_new(l[it], r[it], y[it]);
    }
    swap(l, newl); swap(r, newr); swap(y, newy);
}
#define left_son ((node<<1))
#define right_son ((node<<1)|1)
#define mid ((st+dr)>>1)
class SegTree
{
    int lazy[Nmax<<2];
public:
    void propag(int node)
    {
        if(!lazy[node]) return;
        lazy[left_son] = lazy[right_son] = lazy[node];
        lazy[node] = 0;
    }
    void init()
    {
        lazy[1] = -1;
    }
    void update(int node, int st, int dr, int L, int R, int V)
    {
        if(L <= st && dr <= R)
        {
            lazy[node] = V;
            return;
        }
        propag(node);
        if(L <= mid) update(left_son, st, mid, L, R, V);
        if(mid < R) update(right_son, mid+1, dr, L, R, V);
    }
    int query(int node, int st, int dr, int pos)
    {
        if(st == dr)
            return lazy[node];
        propag(node);
        if(pos <= mid) return query(left_son, st, mid, pos);
            else return query(right_son, mid+1, dr, pos);
    }
} aint;
void add_point(int l, int r, int id)
{
    aint.update(1, 0, h.size()-1, l, r, id);
}
int find_point(int x)
{
    return aint.query(1, 0, h.size()-1, x);
}
void find_graph(int Start, int Finish)
{
    int m = y.size(), n = h.size();
    vector<int> s(m);
    iota(s.begin(), s.end(), 0);
    sort(s.begin(), s.end(), cmp_skywalks);
    reverse(s.begin(), s.end());
    vector<Pair> points;
    aint.init();
    points.push_back({Start, m});
    points.push_back({Finish, m+1});
    y.push_back(0);
    y.push_back(0);
    add_point(Start, Start, m);
    add_point(Finish, Finish, m+1);
    m+=2;
    for(auto it : s)
    {
        points.push_back({ l[it], it });
        points.push_back({ r[it], it });
        int p1, p2;
        p1 = find_point(l[it]);
        p2 = find_point(r[it]);
        if(p1 != -1)
            points.push_back({ l[it], p1 });
        if(p2 != -1)
            points.push_back({ r[it], p2 });
        add_point(l[it], r[it], it);
    }
    vector<vector<Pair>> vx(n), vy(m);
    nr = 0;
    for(auto p : points)
    {
        ++nr;
        vx[p.first].push_back({y[p.second], nr});
        vy[p.second].push_back({x[p.first], nr});
    }
    int i, j;
    for(i=0; i<n; ++i)
    {
        sort(vx[i].begin(), vx[i].end());
        for(j=0; j+1<vx[i].size(); ++j)
            add_edge(vx[i][j].second, vx[i][j+1].second, vx[i][j+1].first - vx[i][j].first);
    }
    for(i=0; i<m; ++i)
    {
        sort(vy[i].begin(), vy[i].end());
        for(j=0; j+1<vy[i].size(); ++j)
            add_edge(vy[i][j].second, vy[i][j+1].second, vy[i][j+1].first - vy[i][j].first);
    }
}
ll dijkstra(int S, int F)
{
    priority_queue< pair<ll, int>, vector<pair<ll,int>>, greater<pair<ll,int>> > heap;
    vector<ll> d(nr+1, LLONG_MAX);
    d[S] = 0;
    heap.push({0, S});
    while(heap.size())
    {
        int node; ll dist;
        tie(dist, node) = heap.top();
        heap.pop();
        if(dist != d[node]) continue;
        if(node == F) return d[F];
        for(auto it : v[node])
            if(d[it.first] > d[node] + it.second)
            {
                d[it.first] = d[node] + it.second;
                heap.push({d[it.first], it.first});
            }
    }
    return -1;
}
ll min_distance(vector<int> X, vector<int> H, vector<int> L, vector<int> R, vector<int> Y, int Start, int Finish)
{
    x = X; h = H; l = L; r = R; y = Y;
    adjust(Start);
    adjust(Finish);
    find_graph(Start, Finish);
    return dijkstra(1, 2);
}
Compilation message (stderr)
walk.cpp: In function 'void adjust(int)':
walk.cpp:70:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         while(id1 < pref.size() && h[pref[id1]] >= y[it])
               ~~~~^~~~~~~~~~~~~
walk.cpp:73:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         while(id2 < suff.size() && h[suff[id2]] >= y[it])
               ~~~~^~~~~~~~~~~~~
walk.cpp: In function 'void find_graph(int, int)':
walk.cpp:196:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(j=0; j+1<vx[i].size(); ++j)
                  ~~~^~~~~~~~~~~~~
walk.cpp:203:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(j=0; j+1<vy[i].size(); ++j)
                  ~~~^~~~~~~~~~~~~| # | 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... |