module main; // https://kmjp.hatenablog.jp/entry/2015/05/15/1100 より // 動的計画法 import std; // 多次元配列をある値で埋める void fill(A, T)(ref A a, T value) if (isArray!A) { alias E = ElementType!A; static if (isArray!E) { foreach (ref e; a) fill(e, value); } else { a[] = value; } } // https://forum.dlang.org/post/k1js2b$1bef$1@digitalmars.com より // 変数の参照 struct Ref(T) { private T* _payload; this(ref T i) { _payload = &i; } @property ref T deref() { return *_payload; } alias deref this; } auto ref_(T)(ref T arg) { return Ref!T(arg); } // B[1 .. j]が狭義単調増加、B[j .. K]が狭義単調減少 // 1 <= j <= N にわたって左右の裾野の長さを調べる int N; int[] A; int[][] L, R; int left(int l, int r) { auto ret = ref_(L[l][r]); if (ret < 0) { ret = 0; foreach (x; 0 .. l) if (A[x] < A[l] && A[l] - A[x] < A[r] - A[l]) ret = max(ret, left(x, l) + 1); } return ret; } int right(int l, int r) { auto ret = ref_(R[l][r]); if (ret < 0) { ret = 0; foreach (x; r + 1 .. N) if (A[x] < A[r] && A[r] - A[x] < A[l] - A[r]) ret = max(ret, right(r, x) + 1); } return ret; } void main() { foreach (_; 0 .. readln.chomp.to!int) { // 入力 N = readln.chomp.to!int; A = readln.split.to!(int[]); // 答えの計算 L = uninitializedArray!(int[][])(N, N); fill(L, -1); R = uninitializedArray!(int[][])(N, N); fill(R, -1); int ma = -1; foreach (i; 0 .. N) { int lm = 0, rm = 0; // 左側 foreach (x; 0 .. i) if (A[x] < A[i]) lm = max(lm, left(x, i) + 1); // 右側 foreach (x; i + 1 .. N) { if (A[x] < A[i]) rm = max(rm, right(i, x) + 1); } ma = max(ma, lm + rm + 1); } // 答えの出力 writeln(ma); } }