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 }
View Code

 

   

posted @ 2020-07-21 18:49  古比  阅读(122)  评论(0编辑  收藏  举报