codeforces864D. Make a Permutation!(贪心)

题意:

给你一个长度为n的序列,元素大小为1~n。让你修改某些元素值,使得整个序列出现的元素不重复(修改值范围为1~N);求在修改操作数最少的前提下,使得修改后的序列字典序最小,

思路:

贪心;由题意知道修改操作最少为1~n没出现过的数的个数。要使得字典序最小,那么就要从头部开始插入,平且插入可选的最小值t(可用优先队列预处理)。

当某个位置的数num出现次数大于二,那么可进行插入判断。两种情况:

1.t<num,,可直接插入

2.t>num。。如果后面直接插入,字典序不是最小的,那么当前数为num,那么往后出现num,不管num与t的大小如何,都必须插入。

代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 2e5+7;
int arr[maxn];
priority_queue<int,vector<int>,greater<int> > pq;
int vis[maxn];
int pd[maxn];
int main()
{
    int n;
    cin>>n;
    int cnt  = 0;
    memset(vis,0,sizeof(vis));
    memset(pd,0,sizeof(pd));
    for(int i = 1;i<=n;i++)
        scanf("%d",arr+i),vis[arr[i]]++;
    for(int i = 1;i<=n;i++)
        if(!vis[i])
            pq.push(i),cnt++;
    for(int i = 1;i<=n;i++)
    {
        int num= arr[i];
        if(vis[num]>=2)
        {
            int t = pq.top();
            if(pd[num]||t<num)
            {
                arr[i] = t;
                vis[num]--;
                pq.pop();
            }
            else
            {
                pd[num] = 1;
            }
        }
    }
    cout<<cnt<<endl;
    for(int i = 1;i<n;i++)
        cout<<arr[i]<<" ";
    cout<<arr[n]<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值