#include #include #include #include #define rep(i,a,b) for(int i=(a);i<(b);i++) #define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--) #define all(x) begin(x),end(x) #define sz(x) (int)(x).size() using namespace std; using namespace atcoder; using ll=long long; using ld=long double; using vll=vector; using vvll=vector; using vi=vector; using vvi=vector; using pll=pair; using mint=modint; // using BoostPoint=boost::polygon::point_data; // using Voronoi=boost::polygon::voronoi_diagram; vi solve(vi a){ int n=sz(a); vi ord(n); iota(all(ord),0); sort(all(ord),[&](int i,int j){ if(a[i]!=a[j])return a[i]p&&a[q]>a[p])nxt.push_back(q); } int h=0,mx=0; for(auto q:nxt){ ll thresh=2ll*a[p]-a[q]; while(hthresh){ mx=max(mx,dp[h][p]); ++h; } dp[p][q]=max(2,mx+1); ans[q]=max(ans[q],dp[p][q]); } } return ans; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); /* O(N^2) 片側だけ考える。 dp[p][q]を「最後の2点がp,qの凸増加部分列の最大長」とする。 h->p->q と遷移する条件は a[p]-a[h] < a[q]-a[p] <=> a[h] > 2*a[p]-a[q]。 pを固定すると、qをa[q]の昇順で見るほど閾値 2*a[p]-a[q] は単調減少する。 そこで候補hをa[h]の降順に並べ、条件を満たしたhを順に追加しながら max dp[h][p] だけ持てば、各qへの遷移はO(1)。 右側は配列を反転して同じ処理をし、各頂点iについて l[i]+r[i]-1 を取る。 */ int T; cin>>T; while(T--){ int N; cin>>N; vi a(N); rep(i,0,N)cin>>a[i]; vi l=solve(a); reverse(all(a)); vi r=solve(a); reverse(all(r)); int ans=1; rep(i,0,N){ ans=max(ans,l[i]+r[i]-1); } cout<