CF1684E MEX vs DIFF

https://www.luogu.com.cn/problem/CF1684E

*2100,CCH 的题目功能真好用!

考虑 DIFFMEX,那么要让 DIFF 尽可能小,MEX 尽可能大。

考虑我们填了最长值域前缀,那么显然我们的每次操作都是不会更劣的。假如把 MEX 后的数填到当前钦定前缀空白,那么 MEX+1,假如所选的数出现的次数只有 1,那么就 DIFF1,否则 DIFF 不变。所以这个答案一定不会更劣。考虑有可能钦定的前缀中有重复的,显然对答案不会影响,这些重复的数不必要去填别处的空。因为填别处的空会让 DIFF+1MEX+1,综合起来不会影响答案。干脆就不填了。

考虑 MEX 最小一定要保证值域上前缀最长,枚举 [0,n] 即可。对于没有出现的就用之后的数填,需要注意的是这里只要判断是否有填的方案即可。假如出现了 k+1 个空那么第 k+1 个空就是最大 MEX

差不多就做完了。。。

#include <bits/stdc++.h> #define int long long #define pb push_back using namespace std; const int N=(int)(1e5+5); map<int,int>mp; int n,m,a[N],vec[N]; void solve() { cin>>n>>m; mp.clear(); for(int i=1;i<=n;i++) { cin>>a[i]; ++mp[a[i]]; } int res=0,num=0,mx=-1; for(int i=0;i<n;i++) { if(!mp.count(i)) { ++num; if(n-res<num||num>m) { mx=i; --num; break ; } continue ; } res+=mp[i]; } // cout<<mx<<" "<<num<<'\n'; if(mx==-1) { cout<<"0\n"; return ; } int tot=0; for(auto it=mp.begin();it!=mp.end();++it) { if((it->first)>=mx) { // cout<<it->first<<" "<<it->second<<'\n'; vec[++tot]=it->second; } } sort(vec+1,vec+1+tot); int nw=tot; res=0; for(int i=1;i<=tot;i++) { if(res+vec[i]<=num) { res+=vec[i]; --nw; } else break ; } cout<<nw<<'\n'; } signed main() { cin.tie(0); ios::sync_with_stdio(false); int T; cin>>T; while(T--) solve(); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16493914.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示