ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1684E MEX vs DIFF

2022-07-19 14:32:02  阅读:199  来源: 互联网

标签:前缀 CF1684E res int vs vec DIFF MEX


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

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

考虑 \(DIFF-MEX\),那么要让 \(DIFF\) 尽可能小,\(MEX\) 尽可能大。

考虑我们填了最长值域前缀,那么显然我们的每次操作都是不会更劣的。假如把 \(MEX\) 后的数填到当前钦定前缀空白,那么 \(MEX+1\),假如所选的数出现的次数只有 1,那么就 \(DIFF-1\),否则 \(DIFF\) 不变。所以这个答案一定不会更劣。考虑有可能钦定的前缀中有重复的,显然对答案不会影响,这些重复的数不必要去填别处的空。因为填别处的空会让 \(DIFF+1\),\(MEX+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;
}


标签:前缀,CF1684E,res,int,vs,vec,DIFF,MEX
来源: https://www.cnblogs.com/xugangfan/p/16493914.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有