CF1406A - Subset Mex 题解

时间:2021-02-03 10:42:05   收藏:0   阅读:0

先对数组升序排序。
排序后,顺次枚举数组中的每个数。
令两个子集分别为 \(A\)\(B\), 读入数组为 \(q\).
对于每个 \(q[i]\):
\((q[i]-1)\notin A\)(即此数的前驱不在 \(A\) 中,换句话说就是 \(\operatorname{mex}(A)=q[i]-1\)) 或 \(q[i]\in A\)(即此数在 \(A\) 中已经存在), 则表示如果将 \(q[i]\) 放入 \(A\) 集合中并不能使 \(\operatorname{mex}(A)\) 增加,故唯有将其放入 \(B\) 集合中才有可能增加答案;
反之,则将其放入 \(A\) 集合中。
枚举完后再遍历一下两个集合,求出答案即可。
需要注意的是,在实现上,因为笔者使用桶维护两个集合,所以在判断 \(q[i]-1\) 是否在桶中时可能会使数组下标为 \(0-1=-1\). 所以笔者在读入时便将每个 \(q[i]\) 都自加 \(1\), 以避免这种情况。但是在统计答案时注意要减一下(还要注意一下 \(\operatorname{mex}\) 比值域大的情况,这里不再赘述)。事实上,用 std::set 啥事没有。
By the way, 这种做法其实还比较麻烦,有更简单的思路。

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn=105;
const int Size=102;

int n;
int q[maxn];
bool A[Size],B[Size];

int mex(bool A[]){
	for(int i=1;i<Size;i++){
		if(!A[i]){return i-1;} 
	}
	return 101;
}

void work(){
	memset(A,false,sizeof A);
	memset(B,false,sizeof B);
	A[0]=B[0]=true;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>q[i];
		q[i]++;
	}
	sort(q,q+n);
	for(int i=0;i<n;i++){
		if(!A[q[i]-1]||A[q[i]]){
			B[q[i]]=true;
		}else{
			A[q[i]]=true;
		}
	}
	cout<<mex(A)+mex(B)<<endl;
}

int main(){
	int T;cin>>T;
	while(T--){work();}
}	
评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!