1 条题解
-
0
这个题目很有意思啊
思路
注意到这道题想让我们贪更多的满足度,我们就尝试贪心一下。
首先,我们先把所有不用开罐器的罐头选上,自然是最省事的。但是这肯定不能满足我们的欲望,毕竟那么多需要开罐器的罐头我们还没有用过呢。那我们如果想要个需要开罐器的罐头,就必然需要选择一些开罐器,用二分就很好找到具体需要多少个开罐器。其实这题到这里就结束了。
详细一点的解释看注释吧
AC代码
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e5+10; int a[N],b[N],c[N]; signed main() { int n,m;scanf("%lld%lld",&n,&m); int A=0,B=0,C=0; for(int i=1,t,x;i<=n;i++) { scanf("%lld%lld",&t,&x); if(t==0)a[A++]=x;//开三个不同的数组存储 if(t==1)b[B++]=x; if(t==2)c[C++]=x; } sort(a,a+A,[](int x,int y){return x>y;});//排序一下,性能更好的物品我们更想要 sort(b,b+B,[](int x,int y){return x>y;}); sort(c,c+C,[](int x,int y){return x>y;}); for(int i=1;i<=A;i++)a[i]+=a[i-1];//前缀和处理一下 for(int i=1;i<=B;i++)b[i]+=b[i-1]; for(int i=1;i<=C;i++)c[i]+=c[i-1]; int ans=A==0?0:a[min(m-1,(int)A-1)];//不需要开罐器的罐头先有多少拿多少 for(int i=0;i<B;i++)//选i个需要开罐器的罐头 { int l=0,r=C-1,res=-1; while(l<=r)//二分 { int mid=l+r>>1; if(c[mid]>=i+1)res=mid,r=mid-1; else l=mid+1; } if(res==-1)continue;//开罐器不够 int remain=m-(i+1)-(res+1); if(remain>=0) ans=max(ans,b[i]+(remain?a[min((int)A-1,remain-1)]:0));//更新答案 } printf("%lld\n",ans); return 0;//完结撒花 }
- 1
信息
- ID
- 8888
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 6
- 标签
- 递交数
- 39
- 已通过
- 12
- 上传者