Educational Codeforces Round 43-E-Well played!(贪心)


题意 :给你n个人的血量和伤害值,然后有两种操作:

1.将某一个人的血量翻倍       2.将一个人的伤害值等于其当前血量

你可以执行a次第一种操作和b次第二种操作,当然你不用非要执行完这a+b次操作,然后问你最终所有人的伤害值之和最大为多少?

一开始想难了,往dp上走了,但是无论如何都不知道怎么去掉第三层循环,后来突发奇想了一波,我第一种操作既然选择了一个人,呢我为什么还要再选择别人呢?可以证明,第一种操作一定是加在一个人身上最优,因此我们可以暴力第一种操作加在谁身上即可,剩下的我们可以按照血量-伤害值排序,然后让靠前的尽量的执行b操作即可。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long 
ll n,a,b,sum[200005],sm[200005];
struct node
{
	ll x,y,z;
}val[200005];
bool comp(node a,node b)
{
	return a.z>b.z;
}
int main(void)
{
	ll ans=0;
	scanf("%lld%lld%lld",&n,&a,&b);b=min(b,n);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&val[i].x,&val[i].y),val[i].z=val[i].x-val[i].y;
	sort(val+1,val+n+1,comp);
	for(int i=1;i<=n;i++)
	{
		sum[i]=sum[i-1]+max(val[i].x,val[i].y);
		sm[i]=sm[i-1]+val[i].y;
	}
	ans+=sum[b]+sm[n]-sm[b];
	if(b==0)
	{
		printf("%lld\n",sm[n]);
		return 0;
	}
	if(a==0)
	{
		printf("%lld\n",ans);
		return 0;
	}
	for(int i=1;i<=n;i++)
	{
		int num=0;ll t=val[i].x;
		for(int j=1;j<=a;j++)
			t*=2ll;
		if(i<=b-1) t=t-max(val[i].x,val[i].y),t+=sum[b],t+=sm[n]-sm[b];
		else t+=sum[b-1],t+=sm[n]-sm[b-1]-val[i].y;
		ans=max(ans,t);
	}
	printf("%lld\n",ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值