zoukankan      html  css  js  c++  java
  • Codeforces 1364C Ehab and Prefix MEXs(贪心)

    题目链接

    题目大意

      给一个a数组,要求定义一个b数组,使得(b_1)~(b_i)之中没有出现的最小的数等于(a_i)

    解题思路

      首先可以肯定的是,如果要给b数组填数的话,一定要优先填较小的数,我们这里用一个变量k来填。其次,后面要出现的数字不能用,但是前面出现过后面不会再出现的数可以用。因为要使得(b_1)~(b_i)之中没有出现的最小的数等于(a_i),所以我们每遍历一个(a_i)就把对应的(b_i)填上去就行了。这里我们就要分情况讨论。

    当k与a_i相等

      我们先考虑把队列里面的一个数放到b数组里面之后队列里还有没有比(a_i)小的数,如果有,无解。如果队列为空说明之前有解的话,那么我们需要填一个比(a_i)大的数,并且这个数不会和(a_i)之后的数相等。这个(a_i)要用队列存起来,一旦有(a_i)比它大就要用上它。

    当k比a_i小

      这时候我们必须填上一个比(a_i)小的数,如果我们队列里面有数的话,肯定是不行的,显然k要比队列里的数大,这样只放一个的话无解。同样的,如果我们放入一个k之后,k+1还是比(a_i)小也是不行的。还有一种情况就是我们要放到数后面还会出现,这样的话显然也是不行的。

    当k比a_i大

      这种情况的话,我们先考虑把队列里面的一个数放到b数组里面之后队列里还有没有比(a_i)小的数,如果有,无解。如果队列是空的那就往k增大的方向找一个后面不会出现的数就行了。

    const int maxn = 2e6+10;
    int vis[maxn], arr[maxn];
    queue<int> tmp;
    vector<int> ans;
    int main() {
        int n; scanf("%d",&n);
        for (int i = 0; i<n; ++i) {
            scanf("%d",&arr[i]);
            ++vis[arr[i]];
        }
        int tot = 0; bool flag = false;
        for (int i = 0; i<n; ++i) {
            if (tot<arr[i]) {
                if (!tmp.empty()&&tmp.front()<arr[i]) flag = true;
                if (vis[tot]) flag = true;
                ans.push_back(tot++);
                if (tot<arr[i]) flag = true;
            }
            else if (tot>=arr[i]) {
                if (!tmp.empty()&&tmp.front()<arr[i]) {
                    if (vis[tmp.front()]) flag = true;
                    ans.push_back(tmp.front()); tmp.pop();
                    if (!tmp.empty()&&tmp.front()<arr[i]) flag = true;
                }
                else {
                    if (tot==arr[i]) tmp.push(tot++);
                    while(vis[tot]) {
                        tmp.push(tot);
                        tot++;
                    }
                    ans.push_back(tot++);
                }
            }
            --vis[arr[i]];
        }
        if (tot>1000000) flag = true;
        if (flag) {
            printf("-1
    ");
            return 0;
        }
        for (int i = 0; i<n; ++i) printf(i==n-1?"%d
    ":"%d ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    VirtualBox 下USB 设备加载的步骤及无法加载的解决办法
    浅析:setsockopt()改善socket网络程序的健壮性
    减小Gcc编译程序的体积
    linux下查看系统进程占用的句柄数
    Linux下高并发socket最大连接数所受的各种限制
    spring-jpa通过自定义sql执行修改碰到的问题
    阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义
    sql select时增加常量列
    CASE WHEN 及 SELECT CASE WHEN的用法
    MYSQL常见运算符和函数
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/13123502.html
Copyright © 2011-2022 走看看