C. Ehab and Prefix MEXs
题意:让我们根据提供的序列,找出另外一个序列
使当前序列满足非负整数中,前k个数中的未出现过的最小整数等于提供的序列中第K个数
思路:我们采用从后面遍历到前面的做法
首先可以确定的是,假如前后两个数字不相同,如 5 6 ,则在6的位置(也就是第二个位置)我们可以填上5,这是确定的
然后再用一个vis数组来标记已经出现过的数字(虽然题目允许相同数字再次出现,但是也可以不出现)
所以剩下的情况就是:有可能出现一连串相同的数字
这个时候,对于相同数字的位置,除了第一个之外(因为第一个要填上上一个位置的数)
我们从base=当前位置-1的情况开始向后遍历,如果遇到vis==1的情况,就跳过然后再继续base++;
为什么这样子是可行的呢?
首先,对于当前计算的区间,我们使用的数字是从当前位置-1的数开始的,所以不会影响到前面序列的操作;
所以只要当前区间可以完成即可 (即无后效性)这也是从后往前遍历的原因
然后对于从首位置就开始出现连续数字的情况,我们再另外讨论即可、
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 int a[maxn]; 5 int ans[maxn]; 6 int vis[maxn]; 7 int main() 8 { 9 int n; 10 scanf("%d",&n); 11 for(int i=1;i<=n;i++) 12 scanf("%d",&a[i]); 13 int judge=0; 14 for(int i=1;i<=n;i++){ 15 if(a[i]>i){ 16 judge=-1; 17 break; 18 } 19 } 20 int limit=1e5+10; 21 if(judge==-1) printf("-1\n"); 22 int nowval=a[n]; 23 vis[nowval]=1; 24 int nowindex=n; 25 int num=1; 26 for(int i=n-1;i>=1;i--){ 27 if(a[i]!=nowval){ 28 ans[nowindex]=a[i]; 29 vis[a[i]]=1; 30 int base=nowindex+1-1; 31 for(int j=nowindex+1;j<=nowindex+num-1;j++){ 32 while(vis[base]){ 33 base++; 34 } 35 ans[j]=base; 36 vis[base]=1; 37 } 38 nowval=a[i]; 39 num=1; 40 nowindex=i; 41 } 42 else{ 43 num++; 44 nowindex=i; 45 } 46 } 47 vis[nowval]=1; 48 int base=0; 49 for(int i=1;i<=num;i++){ 50 while(vis[base]) ++base; 51 ans[i]=base; 52 vis[base]=1; 53 } 54 for(int i=1;i<=n;i++){ 55 printf("%d ",ans[i]); 56 } 57 printf("\n"); 58 return 0; 59 }