![](https://img2020.cnblogs.com/blog/1892543/202012/1892543-20201208184951859-2059514813.png)
- 题意:给你一长度为(n)的数组,有一长度为(k (1le k le n))的区间不断从左往右扫过这个数组,总共扫(n)次,每次扫的区间长度(k=i),在扫的过程中,每次取当前区间内的最小值,存到v中,问每次扫完后v中的数是否能构成一个序列.
- 题解:我们首先特判区间长度(1)和(n)的情况,这很简单,然后我们从([n-1,2])枚举区间长度(也就对应着我们枚举每次选的数(1,2...n)),不难发现,当区间长度为(n-1)时,我们要选两个数,且这两个数只能是(1,2),且(1)必须在数组的第一个位置或者最后一个位置,假如它在([2,n-1])中出现的话,我们当前的区间会向右移动一个单位,所以必然会取两次(1),当然,这同时也要求(1)在数组中只能出现一次,同时(2)必须要在数组中存在,以此向后递推其他的情况,判断我们要选的数是不是在区间的边界即可.
- 代码:
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
int t;
int n;
int a[N];
int ans[N];
int cnt[N];
int main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n;
rep(i,1,n) cnt[i]=0,ans[i]=0;
rep(i,1,n) cin>>a[i],cnt[a[i]]++;
if(cnt[1]>=1) ans[n]=1;
ans[1]=1;
rep(i,1,n){
if(cnt[i]!=1){
ans[1]=0;
break;
}
}
int l=1,r=n; //因为我们每次选完后l或r的位置就被1...i-1的数占掉了,所以要移动.
rep(i,1,n-1){
if(!cnt[i] || cnt[i]>1) break;
if(a[l]==i && cnt[i+1]){
l++;
ans[n-i]=1;
}
else if(a[r]==i && cnt[i+1]){
r--;
ans[n-i]=1;
}
else break;
}
rep(i,1,n) cout<<ans[i];
cout<<'
';
}
return 0;
}