题目描述
On the competitive programming platform CodeCook, every person has a rating graph described by an array of integers a of length n. You are now updating the infrastructure, so you’ve created a program to compress these graphs.
The program works as follows. Given an integer parameter k, the program takes the minimum of each contiguous subarray of length k in a.
More formally, for an array a of length n and an integer k, define the k-compression array of a as an array b of length n−k+1, such that
bj=minj≤i≤j+k−1ai
For example, the 3-compression array of [1,3,4,5,2] is [min{1,3,4},min{3,4,5},min{4,5,2}]=[1,3,2].
A permutation of length m is an array consisting of m distinct integers from 1 to m in arbitrary order. For example, [2,3,1,5,4] is a permutation, but [1,2,2] is not a permutation (2 appears twice in the array) and [1,3,4] is also not a permutation (m=3 but there is 4 in the array).
A k-compression array will make CodeCook users happy if it will be a permutation. Given an array a, determine for all 1≤k≤n if CodeCook users will be happy after a k-compression of this array or not.
Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.
The first line of the description of each test case contains a single integer n (1≤n≤3⋅105) — the length of the array.
The second line of the description of each test case contains n integers a1,…,an (1≤ai≤n) — the elements of the array.
It is guaranteed, that the sum of n for all test cases does not exceed 3⋅105.
Output
For each test case, print a binary string of length n.
The k-th character of the string should be 1 if CodeCook users will be happy after a k-compression of the array a, and 0 otherwise.
Example
input
5
5
1 5 3 4 2
4
1 3 2 1
5
1 3 3 3 2
10
1 2 3 4 5 6 7 8 9 10
3
3 3 2
output
10111
0001
00111
1111111111
000
Note
In the first test case, a=[1,5,3,4,2].
The 1-compression of a is [1,5,3,4,2] and it is a permutation.
The 2-compression of a is [1,3,3,2] and it is not a permutation, since 3 appears twice.
The 3-compression of a is [1,3,2] and it is a permutation.
The 4-compression of a is [1,2] and it is a permutation.
The 5-compression of a is [1] and it is a permutation.
题目大意
给出一个长度为n的数组a[],然后找出a[]中所有长度为k的子序列,并取每个子序列的最小值,从而得到一个新序列。并判断这个新序列是否为排列(含有n个数的排列满足两个条件:1.n个数无重复。2.n个数的取值范围为[1,n]),如果为排列是1,否则是0。
k取[1,n],求得到的01序列。
题目分析
首先对a[]进行桶排序,用cnt[i]记录a[]在等于i的数有几个
。
k=1和n的情况要进行特判,k=1只需要判断整个序列是否为排列即可,k=n时只需要判断序列中是否存在1即可(因为长度为n的子序列只有一个)。
我们可以从大到小枚举所有k(因为k越大,子序列数量越少,越好进行计算),每次查看当前排列最大值是否合法(判断的方法见代码)。因为子序列长度减小,只会增加最大值,并不会影响序列中的其它值。
进而可以推出:如果某一个k的值得到的序列不是排列,那么以后的值(2到k-1)也都不会是排列了。
代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <unordered_map>
#include <queue>
#include <vector>
#include <set>
#include <bitset>
#include <algorithm>
#define LL long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=3e5+5,mod=1e9+7;
int a[N],cnt[N],ans[N];
bool check(int n) //判断a[]序列是否为排列
{
for(int i=1;i<=n;i++)
if(cnt[i]!=1) return false;
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),cnt[a[i]]++;
if(cnt[1]) ans[n]=1; //如果序列中存在1,那么k=n合法
if(check(n)) ans[1]=1; //判断k=1时是否合法
int l=1,r=n;
for(int i=n;i;i--) //从大到小枚举k(i)
{
if(ans[n]==0) break;
ans[i]=1; //当循环到i时,说明k=i合法
int m=n-i+1; //当前k值下排列序列中的最大值m
//判断k=i+1时是否能构成一个排列
if(--cnt[m]==0&&(a[l]==m||a[r]==m)&&cnt[m+1]) //如果a[]中存在两个m或者不存在m+1,就无法构成一个排列
{ //如果m的两边都是比它大的数,那么k=i+1也无法构成一个排列。
if(a[l]==m) l++; //只有当每次的最大值都在l或r上时,才能保证[l,r]区间内的数要大于区间外的数
if(a[r]==m) r--; //收缩区间
}
else break; //如果前面的判断不合法,可直接中断循环
}
for(int i=1;i<=n;i++) printf("%d",ans[i]),cnt[i]=ans[i]=0;
puts("");
}
return 0;
}