CF1364-C. Ehab and Prefix MEXs

题意

给出一个长度为n的数组a,然你找出一个长度为n的数组b,使得:

对于每一个 \(i(1<=i<=n)\)\(MEX(b_1,b_2,...,b_i)=a_i\).

\(MEX\)的定义如下:\(MEX(b_1,b_2,...,b_i)\)为最小的不在\(\{b_1,b_2,...,b_i\}\)集合中的非负整数。

题目保证数组\(a\)是非降序的。


思路

首先考虑到,第一个数字,如果\(a_1\)\(1\)那么\(b_1\)一定为\(0\);如果\(a_1\)\(0\)那么\(b_1\)理论上来说可以是任何数字,之所以说是理论上,是因为这个数字可能对后面会有影响;如果\(a_1\)大于\(1\)那么就不存在这样的数组\(b\)了。

其次考虑到,在\(a_i=a_{i+1}\)的情况下(这里假设\(a_i=x\)),数组中不可能出现数字\(x\),那出现什么情况数组\(b\)才可以出现数字\(x\)呢?只有当\(a_{i-1}=x\not=a_{i}\)的时候(这里假设\(i=p\)),才能出现数字\(x\),并且这个数字\(x\)必须在\(b_{p}\)这个位置出现。原因很明显,数字\(x\)之所以能在\(p\)之前得到,一定是因为\(x\)\(p\)之前最小的,不再集合中的非负整数,如果\(b_p\not=x\)那么当\(i=p\)的时候一定还有\(MEX(b_1,b_2,..,b_p)=x\),不符合要求,所以\(b_p=x\).

现在对于数组\(b\),对于每个满足\(a_i\not=a_{i-1}\)的位置都已经确定了数字,对于第一个位置可能能确定数字。之后从头到尾对数组\(a\)扫描一遍,用一个计数器记录不能确定数字的位置个数,当扫描到一个位置有\(a_i\not=a_{i-1}\)的时候,比较计数器的数量是否大于等于\(a_i-a_{i-1}-1\)。原因是要想在\(i\)这个位置有\(MEX(b_1,b_2,...,b_i)=a_i\)必须要把\(a_{i-1}\)\(a_i-1\)的数字‘填’平,那么你要天平就至少需要\(a_i-a_{i-1}-1\)这么多“空闲”的位置去补充,之所以减去1是因为\(a_{i-1}\)已经在\(b_i\)这个位置补充好了。如果大于那么就把这之间空闲的数字填上去,如果还有空余可以留着给后面的数字补充。

如果最后全部补充完毕还有空闲的数字,那么在不改变\(MEX\)值的情况下可以把这些数字改改成任意值,个人的处理方法是把他们全部变为无穷大。


AC代码

#include <cstdio>
#include <cstring>
#include <iostream>

const int Maxn = 100005;
const int INF = 100001;

int a[Maxn], b[Maxn];
int p[Maxn], s = 0, t = 0;

void solve() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
    }
    if (a[1] != 1) {
        p[t++] = 1;
    } else {
        b[1] = 0;
    }
    bool flag = true;
    for (int i = 2; i <= n; i++) {
        if (a[i] != a[i - 1]) {
            b[i] = a[i - 1];
            if (t - s >= a[i] - a[i - 1] - 1) {
                for (int j = a[i - 1] + 1; j <= a[i] - 1; j++) {
                    b[p[s++]] = j;
                }
            } else {
                flag = false;
                break;
            }
        } else {
            p[t++] = i;
        }
    }
    while (s != t) {
        b[p[s]] = INF;
        s++;
    }
    if (flag) {
        for (int i = 1; i <= n; i++) {
            printf("%d%c", b[i], " \n"[i == n]);
        }
    } else {
        printf("-1\n");
    }
}

int main() {
    solve();
    return 0;
}
posted @ 2021-02-23 16:35  牟翔宇  阅读(54)  评论(0编辑  收藏  举报