题目链接: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;
}