Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
The -movement is boring in the best way: since you can only move right, every valid route spends exactly seconds moving horizontally. All the actual choices are about vertical movement.
Group houses by equal . At one fixed , if the required values have minimum and maximum , then visiting that column means your vertical path must cover the whole interval .
After finishing a column, it is never useful to leave at some middle inside its interval. You can think of each column as being processed from one endpoint to the other, so the only meaningful exit states are and .
Maintain two DP values after each distinct : the minimum vertical cost so far if you end at the lower endpoint , and if you end at the upper endpoint of the current column.
For a column interval , to end at you must have swept the interval and last come from , paying plus the distance from the previous ending height to . Similarly, to end at , aim first for . Add the fixed horizontal cost at the end.
Since YF can move only to , , and , his coordinate never decreases. That immediately kills a bunch of fake complexity: houses must be handled in nondecreasing order of , and the horizontal part of the route is fixed.
No matter what, he starts at and ends at , so he makes exactly
right moves. The problem is only: what is the minimum vertical movement needed?
Group all houses with the same . For one such column, suppose the required values have
To deliver all pizzas at that , the courier's vertical path at that column must cover every required point, so it must cover the whole interval . Points inside the interval do not matter individually. Once you visit both endpoints and , every required in between is automatically passed through if needed. Even if the actual required points are not continuous, moving vertically from to crosses the whole segment anyway.
Now the key greedy/DP observation: after finishing a column, we only need to consider ending at or .
Why? If you have to cover , any route through the column has to reach both extremes. If it ends at some middle point, then its last visited extreme was either or , and moving from that extreme back into the middle only adds extra cost while making the next transition no better than just remembering the relevant endpoint. So middle exits are just expensive indecision. Classic "looks flexible, is actually trash" situation.
So process distinct values from left to right. For each processed column, keep:
For the first transition, pretend the previous interval is just the start height:
with both previous DP values equal to .
Now consider a new column interval and let
To finish this column at , we must sweep the interval and end at . That means we should first reach , then travel from down to . If the previous ending height was , the cost is:
Therefore:
Similarly, to finish at , first reach , then sweep upward:
After processing the column, set , , and continue.
After all columns are processed, we still need to end at . So the minimum vertical cost is
Finally add the fixed horizontal cost:
If multiple houses share the same , sort/group them and keep only the minimum and maximum . If a column has only one relevant height, then and the same formulas still work. No special drama.
Proof of correctness:
First, every valid route uses exactly horizontal moves, because starts at , ends at , and the only horizontal move increases by . Thus minimizing total time is equivalent to minimizing vertical moves.
Second, because never decreases, all houses with smaller must be delivered before houses with larger . Houses with equal are delivered while the courier is at that column. For a fixed column, visiting every required house is equivalent to making the vertical path cover the interval from the minimum required to the maximum required .
Third, after completing a column interval , there exists an optimal route whose ending height is either or . Any route that covers must visit both endpoints. If it ends at a middle height , then after the last endpoint visit it moved some positive distance back toward the middle. Removing or postponing that unnecessary middle movement cannot increase the cost of reaching future required intervals compared with considering the endpoint states directly in the DP transitions. Therefore the two endpoint states are sufficient.
Fourth, the transition formulas are optimal. To end at , the route must have visited at some point during this column, and after that must move from to , costing . Before sweeping down, it must get from the previous ending height to . Taking the cheaper of the two previous endpoint states gives exactly
The argument for ending at is symmetric. By induction over columns, the DP stores the optimal vertical cost for both possible endpoint exits after each column.
Finally, after the last column, the only remaining vertical movement is from the chosen last endpoint to , so taking the minimum of those two possibilities gives the optimal vertical cost overall. Adding the unavoidable horizontal cost gives the minimum delivery time.
Complexity: sorting the houses by costs per test case. The DP scan is . Across all tests, the total number of houses is at most , so this is easily fine. Memory usage is for the points, or effectively besides input storage during the scan.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll Ax, Ay, Bx, By;
cin >> n >> Ax >> Ay >> Bx >> By;
vector<ll> x(n), y(n);
for (ll &v : x) cin >> v;
for (ll &v : y) cin >> v;
vector<pair<ll, ll>> p(n);
for (int i = 0; i < n; i++) p[i] = {x[i], y[i]};
sort(p.begin(), p.end());
ll dpL = 0, dpR = 0;
ll prevL = Ay, prevR = Ay;
for (int i = 0; i < n; ) {
ll curX = p[i].first;
ll l = p[i].second, r = p[i].second;
while (i < n && p[i].first == curX) {
l = min(l, p[i].second);
r = max(r, p[i].second);
i++;
}
ll width = r - l;
ll newL = width + min(dpL + llabs(prevL - r), dpR + llabs(prevR - r));
ll newR = width + min(dpL + llabs(prevL - l), dpR + llabs(prevR - l));
dpL = newL;
dpR = newR;
prevL = l;
prevR = r;
}
ll vertical = min(dpL + llabs(prevL - By), dpR + llabs(prevR - By));
cout << (Bx - Ax) + vertical << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll Ax, Ay, Bx, By;
cin >> n >> Ax >> Ay >> Bx >> By;
vector<ll> x(n), y(n);
for (ll &v : x) cin >> v;
for (ll &v : y) cin >> v;
vector<pair<ll, ll>> p(n);
for (int i = 0; i < n; i++) p[i] = {x[i], y[i]};
sort(p.begin(), p.end());
ll dpL = 0, dpR = 0;
ll prevL = Ay, prevR = Ay;
for (int i = 0; i < n; ) {
ll curX = p[i].first;
ll l = p[i].second, r = p[i].second;
while (i < n && p[i].first == curX) {
l = min(l, p[i].second);
r = max(r, p[i].second);
i++;
}
ll width = r - l;
ll newL = width + min(dpL + llabs(prevL - r), dpR + llabs(prevR - r));
ll newR = width + min(dpL + llabs(prevL - l), dpR + llabs(prevR - l));
dpL = newL;
dpR = newR;
prevL = l;
prevR = r;
}
ll vertical = min(dpL + llabs(prevL - By), dpR + llabs(prevR - By));
cout << (Bx - Ax) + vertical << '\n';
}
return 0;
}