D. Berland Fair(排序,模拟)

, 注意到有些糖果太贵,我们不可能买得起

, s u m n 不妨开一个数组按照糖果从大到小排序,统计当前的糖果价值和sumn

, , s u m n 第一次遍历,剔除掉那些根本买不起的糖果,得到新的sumn

m / s u m n , , m n % s u m n 那么可以完整得买这些糖果m/sumn次,加到答案上去,m还剩n\%sumn

1 n , 然后再从1循环到n,硬模拟买掉部分能买得起的糖果

, , 下一次遍历,再剔除掉那些不可能买得起的糖果,重复上面的步骤

虽然看起来每次遍历都需要O(n)得复杂度,但是因为每次都会剔除糖果

时间复杂度完全ok

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
ll n,m,a[maxn],sumn,ans,s[maxn];
bool com(ll a,ll b){ return a>b; }
int main()
{
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	{
		cin >> a[i];
		sumn+=a[i];
		s[i]=a[i];
	}
	sort(s+1,s+1+n,com);
	ll top=1,shu=n;
	while(1)
	{
		for(int i=top;i<=n;i++)
		{
			if(m>=s[i])	break;//只要能选就行 
			top++,shu--,sumn-=s[i];
		}
		if(sumn==0||top==n+1)	break;
		if(m>=sumn)//能全部全掉就全部选 
		{
			ans+=m/sumn*shu;
			m%=sumn;
		}
		for(int i=1;i<=n;i++)//这里可以用树状数组二分来优化
		{
			if(m<a[i])	continue;
			m-=a[i],ans++;
		}
	}
	cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/106817257