Codeforces Round #670 (Div. 2)

Codeforces Round #670 (Div. 2) 传送门

A. Subset Mex

Description

Given a set of integers (it can contain equal elements).
You have to split it into two subsets A and B (both of them can contain equal elements or be empty). You have to maximize the value of mex(A)+mex(B).
Here mex of a set denotes the smallest non-negative integer that doesn’t exist in the set. For example:
mex({1,4,0,2,2,1})=3
mex({3,3,2,1,3,0,0})=4
mex(∅)=0 (mex for empty set)
The set is splitted into two subsets A and B if for any integer number x the number of occurrences of x into this set is equal to the sum of the number of occurrences of x into A and the number of occurrences of x into B.

Input

The input consists of multiple test cases. The first line contains an integer t (1≤t≤100) — the number of test cases. The description of the test cases follows.
The first line of each test case contains an integer n (1≤n≤100) — the size of the set.
The second line of each testcase contains n integers a1,a2,…an (0≤ai≤100) — the numbers in the set.

Output

For each test case, print the maximum value of mex(A)+mex(B).

input

4
6
0 2 1 5 0 1
3
0 1 2
4
0 2 0 1
6
1 2 3 4 5 6

output

5
3
4
0

Note

In the first test case, A={0,1,2},B={0,1,5} is a possible choice.
In the second test case, A={0,1,2},B=∅ is a possible choice.
In the third test case, A={0,1,2},B={0} is a possible choice.
In the fourth test case, A={1,3,5},B={2,4,6} is a possible choice.

分析

原序列分割成子串A和子串B:
原序列中的元素x出现的次数等于在A中的次数+在子串B中出现的次数
因此
我们先找出原序列中的最大值,然后从0开始枚举一直到原序列的最大值maxk+1
+1是因为到maxk还没有发现存在最小的非负整数,所以+1指的是存在的最小非负整数只能是maxk+1
我们先枚举子串A,假设x在 [ 0,maxk+1 ] 中是第一个数的个数是0即不在原序列中的元素
那么mex(A) = x
否则 x的个数 - 1 ,即放入子串A中 ,然后继续往后枚举
这样就保证了元素 x 即在A中出现也在B中出现(x总出现次数 >= 2)
同理枚举子串B得到mex(B)

Code
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<string>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 1e4;
//ll q_pow(ll a, ll b)
//{
//	ll ret = 1;
//	while(b)
//	{
//		if( b & 1 )
//		{
//			ret = ret * a;
//		}
//		a = a * a;
//		b = b >>1;
//	}
//	return ret;
//
//}
//bool cmp(ll a , ll b)
//{
//	return a > b ;
//}
int vis[maxn];
int Set_A(int n)
{
	for(int i = 0 ; i <= n+1 ; i++)
	{
		if(vis[i]!=0)
		{
			vis[i]--;
		}else
		{
			return i;
			break;
		}
	}
}
int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t;
	cin>>t;
	while( t-- )
	{
		memset(vis,0,sizeof(vis));
		int maxk = -INT_MAX;
		int n;
		cin>>n;
		for(int i = 0 ; i < n ; i++)
		{
			int k ; 
			cin>>k;
			maxk = max(maxk,k);
			vis[k]++;
		}
		int mex_a = Set_A(maxk);
		//cout<<vis[0]<<endl;
		int mex_b = Set_A(maxk);
		//cout<<vis[0]<<endl;
		cout<<mex_a+mex_b<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值