/* *********************************************** Author :kuangbin Created Time :2016/7/23 19:01:05 File Name :F:\ACM\2016ACM\BestCoder\BC84\B.cpp ************************************************ */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const int MAXN = 100010; struct Node { int l,r; int Max; }segTree[MAXN<<2]; int loc[MAXN]; void build(int i,int l,int r) { segTree[i].l = l; segTree[i].r = r; segTree[i].Max = 0; if (l == r){ loc[l] = i; return; } int mid = (l+r)/2; build(i<<1, l, mid); build((i<<1)|1, mid+1, r); } void update(int i, int val) { int x = loc[i]; while(x > 0) { segTree[x].Max = max(segTree[x].Max, val); x >>= 1; } } int queryMax(int i, int l, int r) { if (segTree[i].l == l &&segTree[i].r == r) return segTree[i].Max; int mid = (segTree[i].l + segTree[i].r)/2; if (r <= mid)return queryMax(i<<1,l,r); else if(l > mid)return queryMax((i<<1)|1, l, r); else return max(queryMax(i<<1,l,mid),queryMax((i<<1)|1,mid+1,r)); } int getMin(int i, int v, int left) { if (segTree[i].l == segTree[i].r) return segTree[i].l; if (max(segTree[i<<1].Max,left) >= v ) return getMin(i<<1, v, left); else return getMin((i<<1)|1, v, max(left,segTree[i<<1].Max)); } int T; int a[MAXN]; int b[MAXN]; int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T; int n; scanf("%d",&T); while(T--) { scanf("%d", &n); int tot = 0; for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); b[tot++] = a[i]; } b[tot++] = 0; sort(b,b+tot); tot = unique(b,b+tot) - b; for(int i = 1; i <= n;i++) { a[i] = lower_bound(b,b+tot,a[i])-b; } build(1, 0 , tot-1); for(int i = 1;i <= n;i++) { b[i] = queryMax(1,0,a[i]-1)+1; //printf("i %d %d %d\n",i,a[i],b[i]); update(a[i],b[i]); } build(1, 0 , tot-1); for(int i = 1; i <= n;i++) { a[i] = getMin(1,b[i]-1,0)+1; update(a[i],b[i]); } for(int i = 1;i <= n;i++) { printf("%d",a[i]); if(i