Atcoder 056 D 贪心+二分

D - No Need


Time limit : 2sec / Memory limit : 256MB

Score : 600 points

Problem Statement

AtCoDeer the deer has N cards with positive integers written on them. The number on the i-th card (1iN) is ai. Because he loves big numbers, he calls a subset of the cards good when the sum of the numbers written on the cards in the subset, is K or greater.

Then, for each card i, he judges whether it is unnecessary or not, as follows:

  • If, for any good subset of the cards containing card i, the set that can be obtained by eliminating card i from the subset is also good, card i is unnecessary.
  • Otherwise, card i is NOT unnecessary.

Find the number of the unnecessary cards. Here, he judges each card independently, and he does not throw away cards that turn out to be unnecessary.

Constraints

  • All input values are integers.
  • 1N5000
  • 1K5000
  • 1ai109(1iN)

Partial Score

  • 300 points will be awarded for passing the test set satisfying N,K400.

Input

The input is given from Standard Input in the following format:

N K
a1 a2 ... aN

Output

Print the number of the unnecessary cards.


Sample Input 1

Copy
3 6
1 4 3

Sample Output 1

Copy
1

There are two good sets: {2,3} and {1,2,3}.

Card 1 is only contained in {1,2,3}, and this set without card 1, {2,3}, is also good. Thus, card 1 is unnecessary.

For card 2, a good set {2,3} without card 2, {3}, is not good. Thus, card 2 is NOT unnecessary.

Neither is card 3 for a similar reason, hence the answer is 1.


Sample Input 2

Copy
5 400
3 1 4 1 5

Sample Output 2

Copy
5

In this case, there is no good set. Therefore, all the cards are unnecessary.


Sample Input 3

Copy
6 20
10 4 3 10 25 2

Sample Output 3

Copy
3
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

using namespace std;

int s[5050];

bool cmp(int a,int b)
{
	return a<b;
}

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int n,k;
	scanf("%d%d",&n,&k);
	int num=n,temp,ans=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&temp);
		if(temp>=k) num--;
		else s[ans++]=temp;
	}
	ans--;
	sort(s+1,s+num+1,cmp);
	temp=0;
	while(num>=2)
	{
		temp+=s[num];
		if(s[num-1]+temp<k)
		{
			num--;
			continue;
		}
		if(s[1]+temp>=k)
		{
			ans=0;
			break;
		}
		int l=1,r=num-2;
		while(l+1<r)
		{
			int mid=(l+r)/2;
			if(temp+s[mid]>=k) r=mid;
			else l=mid;
		}
		ans=ans-(num-r);
		num=r;
	}
	printf("%d\n",ans);
	return 0;
}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值