题解:P12733 磨合
引理
这道题目很显然是一道贪心题目,只要从耗时小的物品开始解决就可以解决尽可能多的问题。证明如下:我们可以使用反证法。假设有一个问题所用的时间,要大于我们选择去解决的问题所需要的时间,而最后可以解决的问题却比原来多,那我们一定可以选择耗时更小的问题解决,来节省更多的时间,解决更多的问题。再正推证明:顺序一定是先小后大。先设两个问题,耗时分别为
算法一
排序完成了。根据引理,既然已经知道是贪心了,那么就可以对于每次询问,枚举可以选择多少可以解决的问题,时间复杂度
算法二
这道题目并不需要什么数据结构优化,只需要一个二分就可以解决问题了。根据引理,算法一就是在找到一个问题个数后,再让耗时最大的问题耗时尽可能小,那么我们就想到了二分。
预处理
首先预处理出选用
代码:
sort(a+1,a+n+1);
int sum=0;
for (int i=1;i<=n;i++){
ans[i]=ans[i-1]+(long long)sum+(long long)a[i];
sum+=a[i];
}
处理询问
对于每个输入的时间
秀一下代码:
#include<bits/stdc++.h>
using namespace std;
int a[1000005];
long long ans[1000005];
int main() {
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
int sum=0;
for (int i=1;i<=n;i++){
ans[i]=ans[i-1]+(long long)sum+(long long)a[i];
sum+=a[i];
}
while (m--){
long long t;
scanf("%lld",&t);
int l=1,r=n;
int lst=0;
while (l<=r){
int mid=(l+r)/2;
if (ans[mid]<=t){
l=mid+1;
lst=mid;
}
else{
r=mid-1;
}
}
printf("%d\n",lst);
}
return 0;
}
我觉得已经很详细了,如果有什么问题请直接炮轰我,谢谢。