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