Educational Codeforces Round 43 (Rated for Div. 2) E. Well played!(贪心)

题目链接:http://codeforces.com/contest/976/problem/E


这个题可能对我这种智障不太友好?

首先很容易发现,所有的a都给一个是最优的,具体题解中有证明。然后我们只要枚举a给哪个就好了。我们按照a-b从大到小排序,如果a为0,我们会按照这个顺序依次分配b,所以,当我们枚举a的时候,仅要考虑当前这个点是否分配过b,如果b有剩余,则无序考虑,否则,如果分配过,直接计算,没有分配过,需要取消那个对答案影响最小的b然后分配给我们枚举的点。


代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
struct node
{
	ll a,b;
	bool operator < (const node &o)const
	{
		return (a-b)>(o.a-o.b);
	}
}sv[MAXN];
int n,a,b;
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	scanf("%d%d%d",&n,&a,&b);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&sv[i].a,&sv[i].b);
	}
	sort(sv+1,sv+1+n);
	ll ans=0;
	for(int i=1;i<=n;i++)
		ans+=sv[i].b;
	if(b==0) return 0*printf("%lld\n",ans);
	int lim=min(n,b);
	ll res=0;
	bool flag=false;
	for(int i=1;i<=lim;i++)
		if(sv[i].a-sv[i].b>0)
			ans+=sv[i].a-sv[i].b;
		else
		{
			flag=true;
			lim=i-1;
			break;
		}
	if(b>n) flag=true;
	res=ans;
	for(int i=1;i<=lim;i++)
		res=max(res,ans-sv[i].a+(sv[i].a<<a));
	for(int i=lim+1;i<=n;i++)
		res=max(res,ans+(sv[i].a<<a)-sv[i].b-(flag?0:(sv[lim].a-sv[lim].b)));
	printf("%lld\n",res);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_32872703/article/details/80191463