#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i , a , b) for(int i = (a) ; i <= (b) ; i++)
#define rev(i , a , b) for(int i = (a) ; i >= (b) ; i--)
#define pb push_back
#define pii pair<int,int>
#define endl '\n'
#define F first
#define S second
#define ary array<int, 3 > 
#define all(arr) arr.begin() , arr.end()
constexpr int mod = 998244353;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
void yes(){cout << "Yes" << endl;}
void no(){cout << "No" << endl;}
int binpow(int a , int b, int m = mod){
	int res = 1;
	while(b){if(b&1)res = res * a % m ; a = a * a % m , b >>= 1;}
	return res;
}
int expo(int a , int b){
	int res = 1;
	while(b){if(b&1)res = res * a ; a = a * a  , b >>= 1;}
	return res;
}
int inv(int a , int m = mod){return binpow(a , m - 2 , m);}
pii addPr(pii A , pii B){
	A.F += B.F , A.S += B.S;
	return A;
}
int isIntersecting(pii A , pii B){
	return !(A.F > B.S || B.F > A.S);
}
template<class T> bool chmin(T&a, T b) { bool B = a > b; a = min(a,b); return B; }
template<class T> bool chmax(T&a, T b) { bool B = a < b; a = max(a,b); return B; }
int add(int a , int b , int m = mod){ return ((a + b) % m + m ) % m;}
int mul(int a , int b , int m = mod){ a %= m , b %= m ; return (a * b % m + m ) % m; }
void chadd(int& a , int b , int m = mod){ a = ((a + b) % m + m ) % m; }
void chmul(int& a , int b , int m = mod){ a %= m , b %= m ; a = ( a * b % m + m ) % m ; }
int sigma(int n ){ return n * (n + 1) / 2;}
int sigma(int l , int r){return sigma(r) - sigma(l - 1);}
class SparseTableMn {
private:
    int n, max_log;
    vector<vector<int>> table;
    // Merge function — change this to max, gcd, etc. if needed
    int merge(int a, int b) {
        return min(a, b);  // RMQ
    }
	
public:
    SparseTableMn(const vector<int>& arr) {
        n = arr.size();
        max_log = 32 - __builtin_clz(n); // ceil(log2(n))
        table.assign(max_log, vector<int>(n));
        // Level 0 (length 1 intervals)
        for (int i = 0; i < n; ++i)
            table[0][i] = arr[i];
        // Build higher levels
        for (int k = 1; k < max_log; ++k) {
            for (int i = 0; i + (1 << k) <= n; ++i) {
                table[k][i] = merge(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]);
            }
        }
    }
    // Query in range [l, r] (inclusive)
    int query(int l, int r) {
        int len = r - l + 1;
        int k = 31 - __builtin_clz(len); // floor(log2(len))
        return merge(table[k][l], table[k][r - (1 << k) + 1]);
    }
};
class SparseTableMx {
private:
    int n, max_log;
    vector<vector<int>> table;
    // Merge function — change this to max, gcd, etc. if needed
    int merge(int a, int b) {
        return max(a, b);  // RMQ
    }
	
public:
    SparseTableMx(const vector<int>& arr) {
        n = arr.size();
        max_log = 32 - __builtin_clz(n); // ceil(log2(n))
        table.assign(max_log, vector<int>(n));
        // Level 0 (length 1 intervals)
        for (int i = 0; i < n; ++i)
            table[0][i] = arr[i];
        // Build higher levels
        for (int k = 1; k < max_log; ++k) {
            for (int i = 0; i + (1 << k) <= n; ++i) {
                table[k][i] = merge(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]);
            }
        }
    }
    // Query in range [l, r] (inclusive)
    int query(int l, int r) {
        int len = r - l + 1;
        int k = 31 - __builtin_clz(len); // floor(log2(len))
        return merge(table[k][l], table[k][r - (1 << k) + 1]);
    }
};
struct BIT {
    // single point add, prefix query sum
    vector <int> val;
    int n, offset;
    BIT () = default;
    BIT (int _n, int _offset = 3) : n(_n + _offset * 2), offset(_offset) {
        val.assign(n, 0);
    }
    void add(int p, int v) {
        for (p += offset; p < n; p += p & (-p)) {
            val[p] += v;
        }
    }
    int query(int p) {
        int ans = 0;
        for (p += offset; p > 0; p -= p & (-p)) {
            ans += val[p];
        }
        return ans;
    }
    int query(int l, int r) {
        // query [l, r]
        return query(r) - query(l - 1);
    }
	
	void update(int p , int v){
		int curV = query(p , p);
		add(p , v - curV);
	}
	
    int kth (int k) {
        // 1-index, return kth smallest number
        // 1 <= k && k <= current size
        int ans = 0;
        for (int i = 1 << __lg(n); i > 0; i >>= 1) {
            if (ans + i < n && val[ans + i] < k) {
                k -= val[ans += i];
            }
        }
        return ans - offset + 1;
    }
};
 
 
int SQRT(int num){
	int lo = 1 , hi = 2000000000 , ans = 0;
	while(lo <= hi){
		int mid = (lo + hi) / 2;
		if(mid * mid <= num) ans = mid , lo = mid + 1;
		else hi = mid - 1;
	}
	return ans;
}
 
 
struct hasher{
	int base , mod;
	vector<int> hash , basepow;
	hasher(){
		
	}
	hasher(string s , int _base = 37 , int	 _mod = 1e9 + 7){
		base = _base;
		mod = _mod;
		int n = s.size();
		s = "#" + s + "#";
		
		hash.resize(n+2) , basepow.resize(n + 2);
		hash[0] = 0 , basepow[0] = 1;
		
		for(int i = 1 ; i <= n ; i++){
			
			hash[i] = hash[i-1] * base + (s[i] - 'a' + 1) ;
			hash[i] %= mod;
			basepow[i] = (basepow[i-1] * base)%mod;
		}
		
	}
	
	int getHash(int l , int r){
		int res = hash[r];
		res -= basepow[r - l + 1] * hash[l-1] ;
		res = (res%mod + mod )%mod;
		return res;
	}
	
};
 
struct doubleHasher{
	hasher hash1 , hash2;
	doubleHasher(){
		
	}
	doubleHasher(string s ){
		hash1 = hasher(s , 37 , 999999929);
		hash2 = hasher(s , 37 , 999999937);
	}
	
	int getHash(int l , int r){
		return (1LL << 32) * hash1.getHash(l , r ) +hash2.getHash(l , r);
	}
};
 
// struct hasher{
	// int base , mod;
	// vector<int> hash , basepow , rHash;
	// hasher(){
		
	// }
	// hasher(string s , int _base = 37 , int	 _mod = 1e9 + 7){
		// base = _base;
		// mod = _mod;
		// int n = s.size();
		// s = "#" + s + "#";
		
		// hash.resize(n+2) , basepow.resize(n + 2) , rHash.resize(n + 2);
		// hash[0] = 0 , basepow[0] = 1;
		
		// for(int i = 1 ; i <= n ; i++){
			
			// hash[i] = hash[i-1] * base + (s[i] - 'a' + 1) ;
			// hash[i] %= mod;
			// basepow[i] = (basepow[i-1] * base)%mod;
		// }
 
        // for(int i = n ; i >= 1 ; i--){
            // rHash[i] = rHash[i + 1] * base + (s[i] - 'a' + 1);
            // rHash[i] %= mod;
 
        // }
		
	// }
	
	// int getHash(int l , int r){
		// int res = hash[r];
		// res -= basepow[r - l + 1] * hash[l-1] ;
		// res = (res%mod + mod )%mod;
		// return res;
	// }
 
    // int getRevHash(int l , int r){
        // int res = rHash[l];
        // res -= basepow[r - l + 1] * rHash[r + 1];
        // res = (res % mod + mod) % mod;
        // return res;
    // }
	
	// int isPalindrome(int l , int r){
		// return getHash(l , r) == getRevHash(l , r);
	// }
	
// };
 
// struct doubleHasher{
	// hasher hash1 , hash2;
	// doubleHasher(){
		
	// }
	// doubleHasher(string s ){
		// hash1 = hasher(s , 37 , 999999929);
		// hash2 = hasher(s , 37 , 999999937);
	// }
	
	// int getHash(int l , int r){
		// return (1LL << 32) * hash1.getHash(l , r ) +hash2.getHash(l , r);
	// }
    // int getRevHash(int l , int r){
        // return (1LL << 32) * hash1.getRevHash(l , r) + hash2.getRevHash(l , r);
    // }
	// int isPalindrome(int l , int r){
		// return hash1.isPalindrome(l , r) && hash2.isPalindrome(l , r);
	// }
	
// };
 
 
vector<int> sort_cyclic_shifts(string const& s) {
    int n = s.size();
    const int alphabet = 256;
	vector<int> p(n), c(n), cnt(max(alphabet, n), 0);
    for (int i = 0; i < n; i++)
        cnt[s[i]]++;
    for (int i = 1; i < alphabet; i++)
        cnt[i] += cnt[i-1];
    for (int i = 0; i < n; i++)
        p[--cnt[s[i]]] = i;
    c[p[0]] = 0;
    int classes = 1;
    for (int i = 1; i < n; i++) {
        if (s[p[i]] != s[p[i-1]])
            classes++;
        c[p[i]] = classes - 1;
    }
	vector<int> pn(n), cn(n);
    for (int h = 0; (1 << h) < n; ++h) {
        for (int i = 0; i < n; i++) {
            pn[i] = p[i] - (1 << h);
            if (pn[i] < 0)
                pn[i] += n;
        }
        fill(cnt.begin(), cnt.begin() + classes, 0);
        for (int i = 0; i < n; i++)
            cnt[c[pn[i]]]++;
        for (int i = 1; i < classes; i++)
            cnt[i] += cnt[i-1];
        for (int i = n-1; i >= 0; i--)
            p[--cnt[c[pn[i]]]] = pn[i];
        cn[p[0]] = 0;
        classes = 1;
        for (int i = 1; i < n; i++) {
            pair<int, int> cur = {c[p[i]], c[(p[i] + (1 << h)) % n]};
            pair<int, int> prev = {c[p[i-1]], c[(p[i-1] + (1 << h)) % n]};
            if (cur != prev)
                ++classes;
            cn[p[i]] = classes - 1;
        }
        c.swap(cn);
    }
    return p;
}
vector<int> lcp_construction(const vector<int>& sfx , string& s){
	int n = sfx.size();
	
	vector<int> lcp(n);
	vector<int> isfx(n);
	for(int i = 0 ; i < n ; i++)isfx[sfx[i]] = i;
	
	for(int i = 0 , k = 0 ; i < n ; i++){
		int pos = isfx[i];
		if(pos == 0)continue;
		int j = sfx[pos - 1];
		
		while(i + k < n && j + k < n && s[i + k] == s[j + k])k++;
		lcp[pos] = k;
		if(k > 0)k--;
	}
	
	return lcp;
}
vector<int> suffix_array_construction(string s) {
    s.push_back('$');
    vector<int> sorted_shifts = sort_cyclic_shifts(s);
    sorted_shifts.erase(sorted_shifts.begin());
    return sorted_shifts;
}
struct DisjointSet{
    vector<int> p, sz;
public:
    DisjointSet(int n) : p(n + 1) , sz(n + 1 , 1) { iota(p.begin() , p.end() , 0);}
	int find(int x){ return (x == p[x]) ? x : p[x] = find(p[x]) ;}
	int same(int u , int v){return find(u) == find(v);}
	int size(int u){return sz[find(u)];}
	void merge(int u , int v){
		u = find(u) , v = find(v); if(u == v)return;
		if(sz[u] > sz[v])swap(u , v);
		p[u] = v , sz[v] += sz[u];
	}
};
struct segmentTree{
	struct node{
		int sum;
		node(int s = 0) : sum(s) {}
	};
	node merge(node a , node b){return node(a.sum + b.sum);}
	vector<node> tree;
	int n;
	segmentTree(int _n){n = _n; tree.resize(4 * n);}
	void update(int idx , int val , int id , int lo , int hi){
		if(idx < lo || idx > hi)return;
		if(lo == hi){tree[id].sum = val; return;}
		int mid = (lo + hi)/2;
		update(idx , val , id * 2 + 1 , lo , mid);
		update(idx , val , id * 2 + 2 , mid + 1 , hi);
		tree[id] = merge(tree[id * 2 + 1] , tree[id * 2 + 2]);
	}
	void update(int idx , int val){update(idx , val , 0 , 0 , n - 1);}
	
	node query(int l , int r , int id , int lo , int hi){
		if(hi < l || lo > r)return node();
		if(l <= lo && hi <= r)return tree[id];
		int mid = (lo + hi)/ 2;
		return merge(
			query(l , r , id * 2 + 1 , lo , mid) , 
			query(l , r , id * 2 + 2 , mid + 1 , hi)  
		);
	}
	int query(int l , int r){return query(l , r , 0 , 0 , n - 1).sum;}
};
 
struct lazySegmentTree{
	struct node{
		int sum , inc;
		node(int s = 0) : sum(s) , inc(0)  {}
	};
	node merge(node a , node b){return node(a.sum + b.sum);}
	vector<node> tree;
	int n;
	
	lazySegmentTree(int _n){n = _n; tree.resize(4 * n);}
	
	void push(int id , int lo , int hi){
		
		tree[id].sum += (hi - lo + 1) * tree[id].inc;
		if(lo != hi){
			tree[id * 2 + 1].inc += tree[id].inc;
			tree[id * 2 + 2].inc += tree[id].inc;
		}
		tree[id].inc = 0;
		
	}
	
	void add(int l , int r , int val , int id , int lo , int hi){
		push(id , lo , hi);
		if(lo > r || hi < l)return;
		if(l <= lo && hi <= r){
			tree[id].inc += val;
			push(id , lo , hi);
			return ;
		}
		int mid = (lo + hi) / 2;
		add(l , r , val , id * 2 + 1 , lo , mid);
		add(l , r , val , id * 2 + 2 , mid + 1 , hi);
		tree[id] = merge(tree[id * 2 + 1] , tree[id * 2 + 2]);
	}
	void add(int l , int r , int val){add(l , r , val , 0 , 0 , n-1);}
	
	
	
	node query(int l , int r , int id , int lo , int hi){
		push(id , lo , hi);
		if(lo > r || hi < l)return node();
		if(l <= lo && hi <= r)return tree[id];
		int mid = (lo + hi) / 2;
		return merge(
			query(l , r , id * 2 + 1 , lo , mid),
			query(l , r , id * 2 + 2 , mid + 1 , hi)
		);
	}
	int query(int l , int r){return query(l , r , 0 , 0 , n-1).sum;}
};
class SparseTableGcd {
private:
    int n, max_log;
    vector<vector<int>> table;
    // Merge function — change this to max, gcd, etc. if needed
    int merge(int a, int b) {
        return __gcd(a , b);  // RMQ
    }
	
public:
    SparseTableGcd(const vector<int>& arr) {
        n = arr.size();
        max_log = 32 - __builtin_clz(n); // ceil(log2(n))
        table.assign(max_log, vector<int>(n));
        // Level 0 (length 1 intervals)
        for (int i = 0; i < n; ++i)
            table[0][i] = arr[i];
        // Build higher levels
        for (int k = 1; k < max_log; ++k) {
            for (int i = 0; i + (1 << k) <= n; ++i) {
                table[k][i] = merge(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]);
            }
        }
    }
    // Query in range [l, r] (inclusive)
    int query(int l, int r) {
        int len = r - l + 1;
        int k = 31 - __builtin_clz(len); // floor(log2(len))
        return merge(table[k][l], table[k][r - (1 << k) + 1]);
    }
};
 
const int root = binpow(3 , 119);
const int root_1 = binpow(root , mod-2);
const int root_pw = 1 << 23;
 
 
 
 
void fft(vector<int> & a, bool invert) {
    int n = a.size();
 
    for (int i = 1, j = 0; i < n; i++) {
        int bit = n >> 1;
        for (; j & bit; bit >>= 1)
            j ^= bit;
        j ^= bit;
 
        if (i < j)
            swap(a[i], a[j]);
    }
 
    for (int len = 2; len <= n; len <<= 1) {
        int wlen = invert ? root_1 : root;
        for (int i = len; i < root_pw; i <<= 1)
            wlen = (int)(1LL * wlen * wlen % mod);
 
        for (int i = 0; i < n; i += len) {
            int w = 1;
            for (int j = 0; j < len / 2; j++) {
                int u = a[i+j], v = (int)(1LL * a[i+j+len/2] * w % mod);
                a[i+j] = u + v < mod ? u + v : u + v - mod;
                a[i+j+len/2] = u - v >= 0 ? u - v : u - v + mod;
                w = (int)(1LL * w * wlen % mod);
            }
        }
    }
 
    if (invert) {
        int n_1 = binpow(n, mod -2);
        for (int & x : a)
            x = (int)(1LL * x * n_1 % mod);
    }
}
 
 
 
vector<int> multiply(vector<int>&  a, vector<int>&  b) {
    vector<int> fa(a.begin(), a.end()), fb(b.begin(), b.end());
    int n = 1;
    while (n < a.size() + b.size()) 
        n <<= 1;
    fa.resize(n );
    fb.resize(n);
 
    fft(fa, false);
    fft(fb, false);
    for (int i = 0; i < n; i++)
        fa[i] = (1LL*fa[i]*fb[i])%mod;
    fft(fa, true);
 
    vector<int> result(n);
    for (int i = 0; i < n; i++)
        result[i] = fa[i];
    
    result.resize(a.size() + b.size() - 1);
    return result;
}
void solve(){
	
	int n ; cin >> n;
	vector<int> a(n);
	for(auto& x : a)cin >> x;
	
	set<int> st;
	for(int i = 0 ; i < n ; i++){
		
		auto it = st.upper_bound(a[i]);
		if(it != st.begin()){
			it--;
			st.erase(it);
			st.insert(a[i]);
		}
		else{
			st.insert(a[i]);
		}
	}
	cout << st.size() << endl;
	
	
}
int32_t main(){
	ios_base::sync_with_stdio(false);
    cin.tie(NULL);
	
	
	int tt = 1; 
	cin >> tt;
	
	for(int i = 1 ; i <= tt ; i++){
		solve();
	}
	
	return 0;
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |