1-1875D - Jellyfish and Mex

发布时间 2023-11-16 15:23:24作者: xxj112

题意:
有一个长度为\(n\)的数组,每次删除一个数直到删完,求每次删除后数组的mex的和的最小值。(\(\sum n \leq 5000 , a_i\leq 10^9\)

思路: 排序后,只有从0开始连续的数在会有贡献,对于连续的数,如果要消去他的对答案的贡献,只有全部去掉才行,考虑n的范围小于5000,n^2做法被允许。
// 因为排序后每个数只会受到后边的数字的影响,所以考虑dp。
// dp[i] ,表示值为i的数全部被去掉,对答案的最小贡献,
// dp[i] = dp[j]+cnt[i]*j; (i<j<=n); 时间复杂度允许;
// ans=dp[0]- mex(n) ,(mex(n)为最初的数组的mex值)。
代码:

点击查看代码
#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int inf=1e9+7;
const int N = 1e6 + 10;
int a[N];
void sovle()
{
    int n,x;
    cin>>n;
    vector<int> cnt(n+1,0),dp(n+1,inf); //cnt表示数量,dp数组初始化为inf.
    for(int i=1;i<=n;i++)
    {
       
        cin>>x;
        if(x<n)
        {
            cnt[x]++;
        }
    }
    int m=0;
    dp[n]=0;
    while(cnt[m]) m++; //这里处理出最初的mex值
    for(int i=n-1;i>=0;i--)
    {
        for(int j=n;j>i;j--)
        {
            dp[i]=min(dp[i],dp[j]+cnt[i]*j);
        }
    }
    cout<<dp[0]-m<<"\n";
}   
signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int t=1;
    cin>>t;
    while(t--)
    {
        sovle();
    }
    return 0 ^ 0;
}