

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

#define file "o"
#define ff(i, a, b) for(auto i=(a); i<=(b); ++i)
#define ffr(i, b, a) for(auto i=(b); i>=(a); --i)
#define nl "\n"
#define ss " "
#define pb emplace_back
#define fi first
#define se second
#define sz(s) (int)s.size()
#define all(s) (s).begin(), (s).end()
#define ms(a,x) memset(a, x, sizeof (a))
#define cn continue
#define re exit(0)

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll ran(ll l, ll r)
{
    return uniform_int_distribution<ll> (l, r)(rng);
}

inline void rf()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    if(fopen(file".inp","r"))
    {
        freopen(file".inp","r",stdin);
        freopen(file".out","w",stdout);
    }
}

const int mod=998244353;
const int maxn=3e5+15;
const ll inf=1e18;
const int INF = 2e9;
const int MINF = -2e9;

template<typename T> inline void add(T &x, const T &y)
{
    x+=y;
    if(x>=mod) x-=mod;
    if(x<0) x+=mod;
}

template<typename T> inline bool maxi(T &a, T b)
{
    if(a>=b) return 0;
    a=b; return 1;
}

template<typename T> inline bool mini(T &a, T b)
{
    if(a<=b) return 0;
    a=b; return 1;
}

int n;
vi 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);
}

inline 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;
}

inline 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;
}

inline 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;
}

inline 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);
    ff(i, 1, n) cin >> A[i];

    int lenL = 0;
    P.assign(n + 1, 0); M.assign(n + 1, 0);
    P[0] = INF; M[0] = MINF;
    ff(i, 1, n)
    {
        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;
    ff(j, 1, n) 
    {
        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);
    ff(x, 1, lenL) 
    {
        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);
    ff(y, 1, lenR) 
    {
        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);

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

    ff(x, 1, lenL) 
    {
        int y_curr = min({dp[x - 1], BL[x], n - x});
        if (y_curr < 0) 
        {
            dp[x] = -1;
            cn;
        }
        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;
        maxi(ans, x + dp[x]);
    }
    cout << ans << nl;
}

signed main()
{
    rf();
    int t; cin>>t;
    while (t--) solve();
    re;
}