B. Appending Mex
Initially Ildar has an empty array. He performs nn steps. On each step he takes a subset of integers already added to the array and appends the mex of this subset to the array.
The mex of an multiset of integers is the smallest non-negative integer not presented in the multiset. For example, the mex of the multiset [0,2,3][0,2,3] is 11, while the mex of the multiset [1,2,1][1,2,1] is 00.
More formally, on the step mm, when Ildar already has an array a1,a2,…,am−1a1,a2,…,am−1, he chooses some subset of indices 1≤i1<i2<…<ik<m1≤i1<i2<…<ik<m (possibly, empty), where 0≤k<m0≤k<m, and appends the mex(ai1,ai2,…aik)mex(ai1,ai2,…aik) to the end of the array.
After performing all the steps Ildar thinks that he might have made a mistake somewhere. He asks you to determine for a given array a1,a2,…,ana1,a2,…,an the minimum step tt such that he has definitely made a mistake on at least one of the steps 1,2,…,t1,2,…,t, or determine that he could have obtained this array without mistakes.
Input
The first line contains a single integer nn (1≤n≤1000001≤n≤100000) — the number of steps Ildar made.
The second line contains nn integers a1,a2,…,ana1,a2,…,an (0≤ai≤1090≤ai≤109) — the array Ildar obtained.
Output
If Ildar could have chosen the subsets on each step in such a way that the resulting array is a1,a2,…,ana1,a2,…,an, print −1−1.
Otherwise print a single integer tt — the smallest index of a step such that a mistake was made on at least one step among steps 1,2,…,t1,2,…,t.
Examples
input
Copy
4 0 1 2 1
output
Copy
-1
input
Copy
3 1 0 1
output
Copy
1
input
Copy
4 0 1 2 239
output
Copy
4
题意:现在有个数组,你可以操作n次。对于每一次,从数组里任选数字构成一个子集,然后这个子集里没有出现的第一个最小的数字叫做mex(题目这么规定的- -)。把这个mex追加到数组末尾,那么这个数组就增加了一个。现在问你1-n步里有没有出错的,数组最初是空的。
思路:首先第一步,一定是0不多说了。我们推一下规律,想要得到数字x,如果0~x-1有空缺,那么最小的一定不是x,所以推理结论是:想要得到x,必须有0~x-1所有数字。同时如果已经有0~x所有的了,那么依然可以继续得到0~x的任意一个。
比如0 1 2,我们可以得到新数字只有一个3,而已经出现过的任何一个数字都可以得到,选取0 2 得1 选取1 2 得0 选取0 1 得2。
我们只保存当前已经出现过的最大值mmax,对于新数字,要么是mmax+1,要么是0~mmax任意一个数。这个结论很简单。
都不是输出当前步骤即可。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,a[100010],flag;
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int mmax=-1;
flag=0;
for(int i=1;i<=n;i++)
{
if(a[i]>mmax)
{
if((a[i]-1)!=mmax)
{
flag=1;
printf("%d\n",i);
break;
}
else mmax=a[i];
}
}
if(flag==0)printf("-1\n");
}
return 0;
}