思路:
求最大平均值的板题
考虑二分答案+贪心思想 把每个分母减去答案和分子的积再从大到小排序
参考代码:
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=1e5+10;
ll n,k;
struct PW{
ll ci,vi;
ll s;
}a[N];
bool cmp(PW s1,PW s2){
return s1.s>s2.s;
}
bool check(ll mid){
for(int i=1;i<=n;i++){
a[i].s=a[i].vi-a[i].ci*mid; // 减去积
}
sort(a+1,a+1+n,cmp); // 排序
ll num1=0,num2=0;
for(int i=1;i<=k;i++){
num1+=a[i].vi,num2+=a[i].ci;
}
return num1/num2>=mid; // 最大值比较
}
int main(){
guo312;
int t; cin>>t;
while(t--){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i].ci>>a[i].vi;
}
ll l=0,r=1e4+10;
while(l<r){
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}
思路:
和第一题稍有区别
考虑浮点数二分 最多可以删去K个 不妨先保留 n-k 个 再贪心选后K个
参考代码:
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=2e5+10;
double eps=1e-5; // 控制精度
ll n,k;
struct PW{
double si,ci;
double k;
}a[N];
bool cmp(PW s1,PW s2){
return s1.k>s2.k;
}
bool check(double num){
double re=0,s1=0,s2=0;
for(int i=1;i<=n;i++){
a[i].k=a[i].si*a[i].ci-a[i].si*num; // 减去积
}
sort(a+1,a+1+n,cmp);
int j=n-k;
for(int i=1;i<=j;i++){ // 先选 n-k 个
s1+=a[i].ci*a[i].si,s2+=a[i].si;
}
re=s1/s2;
for(int i=j+1;i<=n;i++){
s1+=a[i].ci*a[i].si,s2+=a[i].si; // 贪心取最大
re=max(re,s1/s2);
}
return re>=num;
}
int main(){
//guo312;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i].si;
}
for(int i=1;i<=n;i++){
cin>>a[i].ci;
}
double l=0,r=1e9*1.0;
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid-eps;
}
printf("%.7lf",l);
return 0;
}