1. Abridged Problem Statement  
Given an integer sequence a₁…aₙ, a “hill” is a contiguous subsequence that strictly increases then strictly decreases (each part at least length 1). Its height is the minimum of the up-run and down-run lengths. A “dale” is strictly decreasing then strictly increasing, and its depth is likewise the minimum of the down- and up-run lengths. For each test case, output the maximum hill height and the maximum dale depth (0 if none exist).

2. Detailed Editorial  

Overview  
We need to scan the sequence and detect for every potential “peak” or “valley” how long the increasing/decreasing runs extend to the left and right. Then for each center we can compute the hill height or dale depth in O(1) and take the maximum.

Definitions  
- up_left[i] = number of consecutive positions t < i such that a[t] < a[t+1], ending at i.  
- down_left[i] = number of consecutive positions t < i such that a[t] > a[t+1], ending at i.  
- up_right[i] = number of consecutive positions t > i such that a[t−1] < a[t], starting at i.  
- down_right[i] = number of consecutive positions t > i such that a[t−1] > a[t], starting at i.

Computation  
1. Forward pass from i=1 to n−1:
   - If a[i] > a[i−1], up_left[i] = up_left[i−1] + 1, else 0.
   - If a[i] < a[i−1], down_left[i] = down_left[i−1] + 1, else 0.
2. Backward pass from i=n−2 down to 0:
   - If a[i] > a[i+1], up_right[i] = up_right[i+1] + 1, else 0.
   - If a[i] < a[i+1], down_right[i] = down_right[i+1] + 1, else 0.
3. For each i:
   - If up_left[i] > 0 and up_right[i] > 0, candidate hill height = min(up_left[i], up_right[i]). Track max.
   - If down_left[i] > 0 and down_right[i] > 0, candidate dale depth = min(down_left[i], down_right[i]). Track max.

Time complexity per test: O(n). Memory O(n).

3. Provided C++ Solution with Detailed Comments  

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

// Overload for printing a pair
template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

// Overload for reading a pair
template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

// Overload for reading a vector
template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
}

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

int n;           // length of the sequence
vector<int> a;   // the sequence

// Read one test case
void read() {
    cin >> n;
    a.resize(n);
    cin >> a;
}

// Solve one test case
void solve() {
    // Arrays to hold run lengths
    vector<int> up_left(n, 0), down_left(n, 0);
    vector<int> up_right(n, 0), down_right(n, 0);

    // Forward scan: compute up_left and down_left
    for(int i = 1; i < n; i++) {
        if(a[i] > a[i - 1]) {
            // we're rising from i-1 to i
            up_left[i] = up_left[i - 1] + 1;
        }
        // else up_left[i] stays 0

        if(a[i] < a[i - 1]) {
            // we're falling from i-1 to i
            down_left[i] = down_left[i - 1] + 1;
        }
        // else down_left[i] stays 0
    }

    // Backward scan: compute up_right and down_right
    for(int i = n - 2; i >= 0; i--) {
        if(a[i] > a[i + 1]) {
            // from i to i+1 is a decrease, so from the right it's an "up"
            up_right[i] = up_right[i + 1] + 1;
        }
        if(a[i] < a[i + 1]) {
            // from i to i+1 is an increase
            down_right[i] = down_right[i + 1] + 1;
        }
    }

    int max_hill = 0, max_dale = 0;

    // Evaluate each position as potential center
    for(int i = 0; i < n; i++) {
        // A hill requires an up-run into i and a down-run out of i
        if(up_left[i] > 0 && up_right[i] > 0) {
            int height = min(up_left[i], up_right[i]);
            max_hill = max(max_hill, height);
        }
        // A dale requires a down-run into i and an up-run out of i
        if(down_left[i] > 0 && down_right[i] > 0) {
            int depth = min(down_left[i], down_right[i]);
            max_dale = max(max_dale, depth);
        }
    }

    // Print results for this test
    cout << max_hill << ' ' << max_dale << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;               // number of test cases
    while(T--) {
        read();
        solve();
    }
    return 0;
}
```

4. Python Solution with Detailed Comments  

```python
import sys
input = sys.stdin.readline

def solve_case():
    n = int(input())
    a = list(map(int, input().split()))

    # Initialize run-length arrays
    up_left = [0]*n
    down_left = [0]*n
    up_right = [0]*n
    down_right = [0]*n

    # Forward pass: build left runs
    for i in range(1, n):
        if a[i] > a[i-1]:
            up_left[i] = up_left[i-1] + 1
        # else stays 0
        if a[i] < a[i-1]:
            down_left[i] = down_left[i-1] + 1
        # else stays 0

    # Backward pass: build right runs
    for i in range(n-2, -1, -1):
        if a[i] > a[i+1]:
            up_right[i] = up_right[i+1] + 1
        if a[i] < a[i+1]:
            down_right[i] = down_right[i+1] + 1

    max_hill = 0
    max_dale = 0

    # Check each index for hills and dales
    for i in range(n):
        # Hill condition: up then down
        if up_left[i] > 0 and up_right[i] > 0:
            height = min(up_left[i], up_right[i])
            if height > max_hill:
                max_hill = height
        # Dale condition: down then up
        if down_left[i] > 0 and down_right[i] > 0:
            depth = min(down_left[i], down_right[i])
            if depth > max_dale:
                max_dale = depth

    print(max_hill, max_dale)

def main():
    T = int(input())
    for _ in range(T):
        solve_case()

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

5. Compressed Editorial  
- Precompute, for each index i, the length of the maximal strictly increasing and decreasing runs ending at i (left) and starting at i (right) in O(n).  
- A hill at i exists if up_left[i]>0 and up_right[i]>0; its height = min(up_left[i], up_right[i]).  
- A dale at i exists if down_left[i]>0 and down_right[i]>0; its depth = min(down_left[i], down_right[i]).  
- Answer is the maximum hill height and maximum dale depth. Time O(n) per test.