Codeforces Round #706 (Div. 2)-B. Max and Mex-题解

45 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

@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 SS initially consisting of nn distinct non-negative integers. A multiset is a set, that can contain some elements multiple times.

You will perform the following operation kk times:

Here max\operatorname{max} of a multiset denotes the maximum integer in the multiset, and mex\operatorname{mex} 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 SS after kk operations will be done.

Input

The input consists of multiple test cases. The first line contains a single integer tt (1t1001\le t\le 100) — the number of test cases. The description of the test cases follows.

The first line of each test case contains two integers nn, kk (1n1051\le n\le 10^5, 0k1090\le k\le 10^9) — the initial size of the multiset SS and how many operations you need to perform.

The second line of each test case contains nn distinct integers a1,a2,,ana_1,a_2,\dots,a_n (0ai1090\le a_i\le 10^9) — the numbers in the initial multiset.

It is guaranteed that the sum of nn over all test cases does not exceed 10510^5.

Output

For each test case, print the number of distinct elements in SS after kk 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, S={0,1,3,4}S=\{0,1,3,4\}, a=mex(S)=2a=\operatorname{mex}(S)=2, b=max(S)=4b=\max(S)=4, a+b2=3\lceil\frac{a+b}{2}\rceil=3. So 33 is added into SS, and SS becomes {0,1,3,3,4}\{0,1,3,3,4\}. The answer is 44.

In the second test case, S={0,1,4}S=\{0,1,4\}, a=mex(S)=2a=\operatorname{mex}(S)=2, b=max(S)=4b=\max(S)=4, a+b2=3\lceil\frac{a+b}{2}\rceil=3. So 33 is added into SS, and SS becomes {0,1,3,4}\{0,1,3,4\}. The answer is 44.


题目大意

MAX是一个集合中最大的数 MEX是一个集合中最小的非负整数 每次操作把 MAX+MEX2\lceil\frac{MAX+MEX}{2}\rceil向上取整,得到的新数放入集合中。 问进行k次操作后,集合中有几种数。


题目分析

考虑两种情况,初始时 MEX\gen 和 MEX\len 。

MEX\gen其实就是MEX=n

读者不妨计算几个试试,将会发现每进行一次操作,MEX就会+1,集合中不同元素的个数也就随之+1。k次操作后,集合中不同元素的个数就变成了n + k

MEX\len

  • 如果k=0,不需要进行操作,答案就是最初的集合中不同元素的个数
  • 否则新生成的数Mnew一定是\geMEX并且\leMAX的,每次操作都是这个数(因为新生成的数不会改变MEX和MAX)。

解题思路

读入n个a后,排序,遍历一遍得到MEX,并且用map去重。

  • 若是MEX\gen,就输出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…