题意:
有一个长度为\(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;
}