卡牌的题解

时间:1s 空间:256M

目录

题目描述:

输入格式:

输出格式:

样例1输入:

样例1输出:

约定与提示:

主要思路:

最后上整体代码:


题目描述:

小信有很多组卡牌,每组卡牌的形式像这样,x,x+1,x+2,...,x+m-1x是这组卡牌的第一张数值,m是这组卡牌的长度。

但有一天他不小心把所有卡牌搞混在了一起。比如他一开始有两组卡牌[2,3,4,5][3,4],混在一起之后变成了[3,3,4,5,4,2]

给定搞混后的卡牌,问你小信最初最少有多少组卡牌。

输入格式:

第一行包含一个整数T,表示测试数据组数。

对于每组测试数据,第一行一个整数n,代表所有卡牌混在一起后的总长度。

第二行n个整数,a_1,a_2,...,a_n,代表混合后的卡牌序列。

输出格式:

对于每组测试数据,输出一个整数表示最初最少有多少组卡牌。

样例1输入:

10

6

2 2 3 4 3 1

5

11 8 7 10 9

6

1000000000 1000000000 1000000000 1000000000 1000000000 1000000000

8

1 1 4 4 2 3 2 3

6

1 2 3 2 3 4

7

10 11 11 12 12 13 13

7

8 8 9 9 10 10 11

8

4 14 5 15 6 16 7 17

8

5 15 6 14 8 12 9 11

5

4 2 2 3 4

样例1输出:

2

1

6

2

2

2

2

2

4

约定与提示:

对于100%的数据, 

1 \le T \le 10^4

1\le n\le 2\cdot 10^5

1 \le a_i\le 10^9

保证每组测试数据中的n加起来的总和不超过2\cdot 10^5


主要思路:

我们会发现这可以贪心,因为如果把一个可以分到这个组里的却不分到这个组,那一定是分的组数是只多不少的。

我们可以用1个map来存储,第一个关键词是每一张卡牌上的数值,第二关键词是这张卡牌有几张?

vector<int> x(n+1);
map<int,int>mp;
for(int i=1;i<=n;i++)
{
	cin>>x[i];
	mp[x[i]]++;
}

注:map是有一个元素就分配一个空间,空间可以不连续,所以不会爆空间。

接着,我们sort一下x(x也可以是数组),for一遍1到n每次取出这一个x[i],如果这个x[i]也就是这张牌没有了,那么就continue,否则就一直向后找比自己大1的,将那张牌数量-1。分好后答案++。

sort(x.begin()+1,x.end());
for(int i=1;i<=n;i++)
{
	int num=x[i];
	if(!mp[num])
	{
		continue;
	}
	while(mp[num])
	{
		mp[num]--;
		num++;
	}
	cnt++;
}

最后上整体代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		vector<int> x(n+1);
		map<int,int>mp;
		for(int i=1;i<=n;i++)
		{
			cin>>x[i];
			mp[x[i]]++;
		}
		sort(x.begin()+1,x.end());
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			int num=x[i];
			if(!mp[num])
			{
				continue;
			}
			while(mp[num])
			{
				mp[num]--;
				num++;
			}
			cnt++;
		}
		cout<<cnt<<'\n';
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值