版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34283998/article/details/82961682
尝试了一下弱化条件想题的方法,还不错?
题目中有三种硬币,并不利于直接贪心.我们不妨先考虑只有两种硬币的情况.按照贪心的思想,应该按照两种硬币的差值(即一个人金币的个数减去银币的个数)进行排序,然后从前选Y个,剩下的X个都为金币.
然后我们将条件加回来,发现性质有了一点点变化.因为有铜币的影响,所以并不能直接选取Y个这样做.但是我们还是可以发现,从前开始选银币,和从后开始选金币的区间是不会相重叠的.因为如果重叠,那么两个交换一下显然更加优秀.所以我们枚举银币从[1,k]选取Y个,金币从[k+1,n]中选取X个.剩下的都为铜币的情况下的最优解.这个东西用个map维护一下就好了
注意在实现的过程中要避免铜币,对答案产生的影响,所以我们可以将金银两种硬币的数量分别减去铜币的数量,最后在同一加回来.就正好不会多,也不会漏.
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int MAXN=1e5+5;
const ll INF=1e18;
ll Zsum,sum,ans=-INF;
ll ans1[MAXN],ans2[MAXN];
int X,Y,Z;
pll a[MAXN];
map<ll,int> cnt;
bool cmp(pll p,pll q){return p.first-p.second<q.first-q.second;}
int main(){
scanf("%d%d%d",&X,&Y,&Z);
int n=X+Y+Z;
for(int i=1;i<=n;i++){
ll a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
Zsum+=c;
a-=c,b-=c;
::a[i].first=a,::a[i].second=b;
}
sort(a+1,a+n+1,cmp);
int st,ed;
sum=0;
for(st=1;st<=Y;st++){
cnt[a[st].second]++;
sum+=a[st].second;
}
ans1[Y]=sum;
for(;st<=n-X;st++){
if(a[st].second<=cnt.begin()->first){ans1[st]=sum;continue;}
sum-=cnt.begin()->first;
if(cnt.begin()->second>1) cnt.begin()->second--;
else cnt.erase(cnt.begin());
cnt[a[st].second]++;
sum+=a[st].second;
ans1[st]=sum;
}
cnt.clear();
sum=0;
for(ed=n;ed>n-X;ed--){
cnt[a[ed].first]++;
sum+=a[ed].first;
}
ans2[n-X+1]=sum;
for(;ed>=Y;ed--){
if(a[ed].first<=cnt.begin()->first){ans2[ed]=sum;continue;}
sum-=cnt.begin()->first;
if(cnt.begin()->second>1) cnt.begin()->second--;
else cnt.erase(cnt.begin());
cnt[a[ed].first]++;
sum+=a[ed].first;
ans2[ed]=sum;
}
for(int i=Y;i<=n-X;i++)
ans=max(ans,ans1[i]+ans2[i+1]);
printf("%lld",ans+Zsum);
}