## 1) Abridged problem statement

You are given a polyline “mountain” with vertices \((1,y_1),(2,y_2),\dots,(n,y_n)\). Two climbers start at the ends: one at \((1,y_1)\) and the other at \((n,y_n)\). They move along the polyline edges (possibly stopping or moving at any speeds), but **at every moment they must be at the same height (same \(y\))**.  
Given that \(y_1=y_n=0\), determine whether it is possible for them to **meet at the same point** on the mountain while respecting the equal-height constraint. Output `"YES"` or `"NO"`.

---

## 2) Detailed editorial (how the solution works)

### Key idea: what does “same height at all times” imply?
At any moment both climbers have the same vertical coordinate \(y\). So the process can be viewed as choosing a height \(y(t)\) over time, and having each climber stand somewhere on their respective side of the mountain where the polyline has that height.

However, unlike the classic “mountain climbing” theorem (which often assumes non-negative heights), here heights may be negative, which can make meeting impossible.

### Maintain an invariant: a *feasible height interval*
The provided solution uses a greedy two-pointer approach.

- Let `l` be the current vertex index of the **left** climber (starting `l=0`).
- Let `r` be the current vertex index of the **right** climber (starting `r=n-1`).
- Maintain an interval `[low, high]` of heights such that:

> From the current positions (somewhere between vertices near `l` and `r`), the climbers can “synchronize” at **any** common height in `[low, high]` without leaving their already-reachable regions.

Initially:
- both are at height 0, so `low = high = 0`.

At each step we try to move inward (increase `l` or decrease `r`) while keeping feasibility.

### What does it mean to “move one step inward”?
Consider trying to advance the left climber from vertex `l` to `l+1`. The height at the next vertex is `h[l+1]`.

There are four cases (the code checks them in this order):

#### Case 1: Safe advance (no interval change)
If `h[l+1]` lies inside the current feasible interval `[low, high]`, then the left climber can advance to `l+1` while the right climber can adjust (possibly by moving/stopping) to maintain equal height within the same interval.  
So we do `l++`.  
Symmetrically, if `h[r-1]` is inside `[low, high]`, we can do `r--`.

#### Case 2: Both next vertices are above `high` (must climb higher)
If `h[l+1] > high` and `h[r-1] > high`, then to keep equal height, they must raise their synchronized height above `high`. The best we can do is raise `high` to the **smaller** of those two next heights, and move that corresponding pointer inward, because that side reaches the new required ceiling first.
- If `h[l+1] < h[r-1]`, set `high = h[l+1]`, `l++`
- else set `high = h[r-1]`, `r--`

This preserves feasibility: now `[low, high]` expands upward just enough to allow progress.

#### Case 3: Both next vertices are below `low` (must descend lower)
Similarly, if `h[l+1] < low` and `h[r-1] < low`, they must lower their synchronized height below `low`. We decrease `low` to the **larger** of the two (closest to current interval), and move that pointer.
- If `h[l+1] > h[r-1]`, set `low = h[l+1]`, `l++`
- else set `low = h[r-1]`, `r--`

#### Case 4: Mixed situation ⇒ impossible
If one side would need to go above `high` while the other would need to go below `low` (or one fits but neither of the “safe advance” checks passed), then there is no single height that both can share while moving inward. Then output `"NO"`.

### Termination
We repeat until `l >= r`. At that point, their reachable regions overlap (they have effectively met or crossed), and the algorithm concludes `"YES"`.

### Complexity
Each step increments `l` or decrements `r`, so there are at most `n-1` steps:
- Time: **O(n)**
- Memory: **O(1)** beyond the input array.

This fits the strict time limit.

---

## 3) Provided C++ solution with detailed line-by-line comments

```cpp
#include <bits/stdc++.h>
using namespace std;

// Pretty-print a pair: (a,b) -> "a b"
template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

// Read a pair from input: reads two values into x.first and x.second
template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

// Read a whole vector: assumes vector already has correct size
template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for (auto& x : a) {
        in >> x;
    }
    return in;
}

// Print a vector (space-separated)
template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for (auto x : a) {
        out << x << ' ';
    }
    return out;
}

int n;          // number of vertices
vector<int> h;  // heights y1..yn

// Reads input into n and h
void read() {
    cin >> n;           // read n
    h.resize(n);        // allocate n heights
    cin >> h;           // read all heights
}

void solve() {
    // Two pointers:
    // l = current index of left climber (starting at 0 meaning vertex 1)
    // r = current index of right climber (starting at n-1 meaning vertex n)
    int l = 0, r = n - 1;

    // Maintain feasible synchronized height interval [low, high]
    // Initially both are at height 0 (given y1=yn=0)
    int low = 0, high = 0;

    // While they haven't met/crossed in index-space
    while (l < r) {
        // Case 1a: left can move to l+1 without changing feasible interval
        if (h[l + 1] >= low && h[l + 1] <= high) {
            l++; // advance left side
        }
        // Case 1b: right can move to r-1 without changing feasible interval
        else if (h[r - 1] >= low && h[r - 1] <= high) {
            r--; // advance right side
        }
        // Case 2: both next vertices are above current high -> must raise high
        else if (h[l + 1] > high && h[r - 1] > high) {
            // Raise high to the smaller of the two (minimal necessary raise),
            // and move the side that reaches that smaller height.
            if (h[l + 1] < h[r - 1]) {
                high = h[l + 1];
                l++;
            } else {
                high = h[r - 1];
                r--;
            }
        }
        // Case 3: both next vertices are below current low -> must lower low
        else if (h[l + 1] < low && h[r - 1] < low) {
            // Lower low to the larger (closest) of the two, and move that side.
            if (h[l + 1] > h[r - 1]) {
                low = h[l + 1];
                l++;
            } else {
                low = h[r - 1];
                r--;
            }
        }
        // Case 4: incompatible requirements -> cannot keep same height
        else {
            cout << "NO" << endl;
            return;
        }
    }

    // If we finished the loop, they can meet/cross with synchronization
    cout << "YES" << endl;
}

int main() {
    ios_base::sync_with_stdio(false); // fast I/O
    cin.tie(nullptr);                 // untie cin/cout for speed

    int T = 1; // only one test case here
    // cin >> T; // (disabled)

    for (int test = 1; test <= T; test++) {
        read();   // read n and heights
        solve();  // output YES/NO
    }

    return 0;
}
```

---

## 4) Python solution (same logic, detailed comments)

```python
import sys

def solve() -> None:
    data = list(map(int, sys.stdin.read().strip().split()))
    n = data[0]
    h = data[1:1+n]

    # Two pointers at the ends (0-based indices)
    l, r = 0, n - 1

    # Feasible synchronized height interval [low, high]
    # Start at height 0 on both ends (given by statement)
    low = high = 0

    while l < r:
        # Case 1: safe advance from left if next height is within [low, high]
        if low <= h[l + 1] <= high:
            l += 1

        # Case 1 (symmetric): safe advance from right
        elif low <= h[r - 1] <= high:
            r -= 1

        # Case 2: both next heights above current high -> must raise high
        elif h[l + 1] > high and h[r - 1] > high:
            # Raise to the smaller one and move that pointer inward
            if h[l + 1] < h[r - 1]:
                high = h[l + 1]
                l += 1
            else:
                high = h[r - 1]
                r -= 1

        # Case 3: both next heights below current low -> must lower low
        elif h[l + 1] < low and h[r - 1] < low:
            # Lower to the larger one and move that pointer inward
            if h[l + 1] > h[r - 1]:
                low = h[l + 1]
                l += 1
            else:
                low = h[r - 1]
                r -= 1

        # Case 4: incompatible; cannot choose a single synchronized height
        else:
            sys.stdout.write("NO\n")
            return

    sys.stdout.write("YES\n")

if __name__ == "__main__":
    solve()
```

---

## 5) Compressed editorial

Maintain pointers `l=0`, `r=n-1` and a feasible synchronized height interval `[low, high]` (start `[0,0]`).  
While `l<r`:

- If `h[l+1]∈[low,high]`, do `l++`; else if `h[r-1]∈[low,high]`, do `r--`.
- Else if both `h[l+1], h[r-1] > high`, raise `high` to `min(h[l+1], h[r-1])` and move the side achieving it.
- Else if both `h[l+1], h[r-1] < low`, lower `low` to `max(h[l+1], h[r-1])` and move that side.
- Otherwise, impossible ⇒ `"NO"`.

If the loop ends, they can meet ⇒ `"YES"`.  
Runs in O(n).