1475D. Cleaning the Phone(二分+前缀和)

传送门

因为 b i b_i bi只有 1 1 1 2 2 2两种,考虑分成 a 1 , a 2 a1,a2 a1,a2两个数组装相应的 a i a_i ai

a 1 a1 a1里的 a i a_i ai b i = 1 b_i=1 bi=1,那么 a 1 a1 a1里的物品具有明显的优劣关系, a i a_i ai越大的越好

所以 a 1 , a 2 a1,a2 a1,a2按照 a i a_i ai从大到小排序

枚举 a 1 a1 a1数组取前 i i i个物品

此时可以使用二分去快速得到一个最小的 i n d e x index index使得取走前 i n d e x index index大的 a 2 a2 a2元素

满足条件,然后更新答案即可

dp似乎是行不通的(可能可以???)…

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e5+10;
const int inf = 1e15;
int t,n,m,a[maxn],b[maxn],a1[maxn],a2[maxn],pre[maxn];
bool com(int a,int b){ return a>b; }
signed main()
{
	int t; cin >> t;
	while( t-- )
	{
		cin >> n >> m;
		for(int i=1;i<=n;i++)	scanf("%lld",&a[i]);
		for(int i=1;i<=n;i++)	scanf("%lld",&b[i]); 
		a1[0]=a2[0]=0;
		for(int i=1;i<=n;i++)
		{
			if( b[i]==1 )	a1[++a1[0]] = a[i];
			else	a2[++a2[0]] = a[i];
		}
		sort( a1+1,a1+1+a1[0],com );
		sort( a2+1,a2+1+a2[0],com );
		for(int i=1;i<=a2[0];i++)	pre[i] = pre[i-1]+a2[i];
		//ö��ѡ��s��
		int ans = inf,sum=0;
		for(int i=1;i<=a1[0];i++)
		{
			sum+=a1[i];
			if( sum>=m ){ ans=min(i,ans); break; }
			int yu = m-sum;
			int index = lower_bound( pre+1,pre+1+a2[0],yu )-pre;
			if( index==a2[0]+1 )	continue;
			ans = min( ans,i+index*2 );
		} 
		int index = lower_bound( pre+1,pre+1+a2[0],m )-pre;
		if( index!=a2[0]+1 )
			ans = min( ans,index*2 );
		if( ans==inf )	cout << -1 << endl;
		else	cout << ans << endl;
	}
}
  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值