聚会(思维)

聚会(思维)

链接:https://ac.nowcoder.com/acm/contest/37160/E
来源:牛客网

题目描述
一场聚会,每个人都有一个活跃度。一个聚会的活跃度定义为这些人的活跃度组成的可重复数字集合的子集和组成的集合中未出现的最小正整数。现在需要你求出这个聚会的活跃度的值。

输入描述:
第一行一个整数 n (1≤n≤10 5),代表有 n 个人。

第二行 n 个整数,第 i 个数代表第 i 个人的活跃度 ai( 1≤ai≤109 )。

输出描述:
一个整数,输出这个聚会的活跃度值。

示例1
输入

3
1 2 3

输出
7

说明
聚会的集合为{1,2,3} ,子集有{},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3},子集的和分别为 0,1,2,3,3,4,5,6,未出现的最小正整数为 7。

备注:
原集合和子集都是可重复数字集合。

思路: 按照题所给思路算肯定是不现实的,所以要另找办法,假设当前满足条件所能凑出来的范围最大值为x,即我们现在能凑成[0,x]中的任意数,当来了一个新元素a, 如果a<=x+1, 区间由[0,x]变为[0,x]并[a,x+a]=[0,x+a] (显然,新元素来后,能凑成的最大正整数一定是x+a,那[a,x+a]中的数是否一定都能凑成呢,新元素来之前,我们已经能凑成[0,x]中的任意数,那a+1,a+2…a+x也是一定能凑出来的),那如果a>x+1, 区间由[0,x]变为[0,x]并[a,x+a]=[0,x]并[x+2,x+a],缺少x+1,此时x+1就是我们要求的答案,当然要先从小到大排序,以保证维护的正确性

AC代码:

#include<bits/stdc++.h> 
using namespace std;
#define int long long
int a[110000];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(nullptr);
	int i,j,k,n;
	cin>>n;
	for(i=0;i<n;i++)
	cin>>a[i];
	sort(a,a+n);
	int ans=0;//起初为0,是我们能凑出来的范围最大值
	for(i=0;i<n;i++)
	{
		if(a[i]<=ans+1)
		ans+=a[i];
		else
		break;
	}
	cout<<ans+1<<"\n";
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值