本文已参与「新人创作礼」活动,一起开启掘金创作之路。
@TOC
Codeforces Round #706 (Div. 2)-B. Max and Mex
传送门 Time Limit: 1 second Memory Limit: 256 megabytes
Problem Description
You are given a multiset initially consisting of distinct non-negative integers. A multiset is a set, that can contain some elements multiple times.
You will perform the following operation times:
Here of a multiset denotes the maximum integer in the multiset, and of a multiset denotes the smallest non-negative integer that is not present in the multiset. For example:
Your task is to calculate the number of distinct elements in after operations will be done.
Input
The input consists of multiple test cases. The first line contains a single integer () — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers , (, ) — the initial size of the multiset and how many operations you need to perform.
The second line of each test case contains distinct integers () — the numbers in the initial multiset.
It is guaranteed that the sum of over all test cases does not exceed .
Output
For each test case, print the number of distinct elements in after operations will be done.
Sample Input
5
4 1
0 1 3 4
3 1
0 1 4
3 0
0 1 4
3 2
0 1 2
3 2
1 2 3
Sample Onput
4
4
3
5
3
Note
In the first test case, , , , . So is added into , and becomes . The answer is .
In the second test case, , , , . So is added into , and becomes . The answer is .
题目大意
MAX是一个集合中最大的数 MEX是一个集合中最小的非负整数 每次操作把 向上取整,得到的新数放入集合中。 问进行k次操作后,集合中有几种数。
题目分析
考虑两种情况,初始时 MEXn 和 MEXn 。
MEXn其实就是MEX=n
读者不妨计算几个试试,将会发现每进行一次操作,MEX就会+1,集合中不同元素的个数也就随之+1。k次操作后,集合中不同元素的个数就变成了
n + k
MEXn
- 如果k=0,不需要进行操作,答案就是最初的集合中不同元素的个数
- 否则新生成的数Mnew一定是MEX并且MAX的,每次操作都是这个数(因为新生成的数不会改变MEX和MAX)。
解题思路
读入n个a后,排序,遍历一遍得到MEX,并且用map去重。
- 若是MEXn,就输出n+k
- 否则
- 如果k=0,就直接输出map.size
- 否则,计算一次新生成的数Mnew,并将Mnew插入到map中,输出map.size
map可以设置为map<int,bool>,map.size就是集合中不同元素的个数
AC代码
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int a[100010];
int main()
{
int N;
cin >> N;
while (N--) //N个测试样例
{
int n, k;
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]); //读入
}
sort(a, a + n); //排序
int Me = 0;
map<int, bool> mp;
for (int i = 0; i < n; i++)
{
mp[a[i]] = 1; //a[i]出现过,插入map
if (a[i] == Me) //如果目前的Me出现过,就Me++
Me++;
}
if (Me >= n) //第一种情况,直接输出
{
printf("%d\n", n + k);
continue;
}
else //否则
{
map<int, bool>::iterator it = mp.end();
it--;
int Ma = it->first; //Ma就是map中的最后一个的first
int Mnew = (Ma + Me) / 2 + ((Ma + Me) % 2 != 0); //操作后新生成的数
if (k != 0) //k不等于0
mp[Mnew] = 1;
printf("%d\n", mp.size());
}
}
return 0;
}
同步发文于我的CSDN,原创不易,转载请附上原文链接哦~
Tisfy:blog.csdn.net/Tisfy/artic…