Codeforces Global Round 12 D. Rating Compression(思维)

题目描述

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; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值