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

const int INF = 2e9;
const int MINF = -2e9;

int n;
vector<int> A, P, M, Q, K, BL, BR, tree_seg;

void build(int node, int l, int r) {
    if (l == r) {
        tree_seg[node] = BR[l];
        return;
    }
    int mid = l + (r - l) / 2;
    build(2 * node, l, mid);
    build(2 * node + 1, mid + 1, r);
    tree_seg[node] = min(tree_seg[2 * node], tree_seg[2 * node + 1]);
}

int query(int node, int l, int r, int ql, int qr, int x) {
    if (l > qr || r < ql || tree_seg[node] >= x) return -1;
    if (l == r) return l;
    int mid = l + (r - l) / 2;
    int res = query(2 * node, l, mid, ql, qr, x);
    if (res != -1) return res;
    return query(2 * node + 1, mid + 1, r, ql, qr, x);
}

int getMaxY_Q(int val, int lenR) {
    int low = 0, high = lenR, ans = 0;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (Q[mid] > val) { ans = mid; low = mid + 1; } 
        else high = mid - 1;
    }
    return ans;
}

int getMaxY_K(int val, int lenR) {
    int low = 0, high = lenR, ans = 0;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (K[mid] < val) { ans = mid; low = mid + 1; } 
        else high = mid - 1;
    }
    return ans;
}

int getMaxX_P(int val, int lenL) {
    int low = 0, high = lenL, ans = 0;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (P[mid] > val) { ans = mid; low = mid + 1; } 
        else high = mid - 1;
    }
    return ans;
}

int getMaxX_M(int val, int lenL) {
    int low = 0, high = lenL, ans = 0;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (M[mid] < val) { ans = mid; low = mid + 1; } 
        else high = mid - 1;
    }
    return ans;
}

void solve() {
    cin >> n;
    A.assign(n + 1, 0);
    for (int i = 1; i <= n; i++) cin >> A[i];

    int lenL = 0;
    P.assign(n + 1, 0); M.assign(n + 1, 0);
    P[0] = INF; M[0] = MINF;
    for (int i = 1; i <= n; i++) {
        if (i == 1) { lenL = 1; P[1] = A[1]; M[1] = A[1]; } 
        else {
            if (A[i] < P[i - 1]) { lenL = i; P[i] = A[i]; M[i] = M[i - 1]; } 
            else if (A[i] > M[i - 1]) { lenL = i; P[i] = P[i - 1]; M[i] = A[i]; } 
            else break;
        }
    }

    int lenR = 0;
    Q.assign(n + 1, 0); K.assign(n + 1, 0);
    Q[0] = INF; K[0] = MINF;
    for (int j = 1; j <= n; j++) {
        int idx = n - j + 1;
        if (j == 1) { lenR = 1; Q[1] = A[idx]; K[1] = A[idx]; } 
        else {
            if (A[idx] < Q[j - 1]) { lenR = j; Q[j] = A[idx]; K[j] = K[j - 1]; } 
            else if (A[idx] > K[j - 1]) { lenR = j; Q[j] = Q[j - 1]; K[j] = A[idx]; } 
            else break;
        }
    }

    BL.assign(lenL + 1, 0);
    for (int x = 1; x <= lenL; x++) {
        if (x == 1) BL[x] = max(getMaxY_Q(A[1], lenR), getMaxY_K(A[1], lenR));
        else {
            if (A[x] < P[x - 1]) BL[x] = getMaxY_Q(A[x], lenR);
            else BL[x] = getMaxY_K(A[x], lenR);
        }
    }

    BR.assign(lenR + 1, 0);
    for (int y = 1; y <= lenR; y++) {
        int idx = n - y + 1;
        if (y == 1) BR[y] = max(getMaxX_P(A[n], lenL), getMaxX_M(A[n], lenL));
        else {
            if (A[idx] < Q[y - 1]) BR[y] = getMaxX_P(A[idx], lenL);
            else BR[y] = getMaxX_M(A[idx], lenL);
        }
    }

    tree_seg.assign(4 * lenR + 5, 0);
    if (lenR > 0) build(1, 1, lenR);

    vector<int> dp(lenL + 1, -1);
    dp[0] = lenR;
    int ans = dp[0];

    for (int x = 1; x <= lenL; x++) {
        int y_curr = min({dp[x - 1], BL[x], n - x});
        if (y_curr < 0) {
            dp[x] = -1;
            continue;
        }
        int limit = min(lenR, n - x);
        if (y_curr < limit) {
            int k = query(1, 1, lenR, y_curr + 1, limit, x);
            if (k != -1) y_curr = k - 1;
            else y_curr = limit;
        }
        dp[x] = y_curr;
        ans = max(ans, x + dp[x]);
    }
    cout << ans << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    if (cin >> t) {
        while (t--) solve();
    }
    return 0;
}