时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
Kanade selected n courses in the university. The academic credit of the i-th course is s[i] and the score of the i-th course is c[i].
At the university where she attended, the final score of her is
Now she can delete at most k courses and she want to know what the highest final score that can get.
输入描述:
The first line has two positive integers n,k The second line has n positive integers s[i] The third line has n positive integers c[i]
输出描述:
Output the highest final score, your answer is correct if and only if the absolute error with the standard answer is no more than 10-5
示例1
输入
复制
3 1 1 2 3 3 2 1
输出
复制
2.33333333333
说明
Delete the third course and the final score is
备注:
1≤ n≤ 105 0≤ k < n 1≤ s[i],c[i] ≤ 103
思路:
01分数规划模板题。
所谓的01分数规划,就是先对式子变形,然后二分出一个解,带入式子判断是否合法。
如本题,先二分出一个解x。然后判断是否还有比x大的解,则式子为:
式子可以变形为:
然后可以根据这个式子计算出每门课的贡献值:
将贡献值排序,取最大的n-k个数。如果和大于0,就说明还有比x大的解。否则说明没有比x大的解。
这里介绍一个STL函数,nth_element(first,nth,last,cmp);
nth_element仅排序第n个元素(从0开始索引),即将位置n(从0开始)的元素放在第n大的位置,处理完之后,默认排在它前面的元素都不比它大,排在它后面的元素都不比它小。
可以很快的找出前k大的元素。
代码:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
const double eps = 1e-6;
int n,k;
double dis[MAXN];
struct node
{
ll s,c;
}p[MAXN];
bool cmp(double a,double b)
{
return a>b;
}
bool check(double x)
{
for(int i=0;i<n;i++)
dis[i]=p[i].s*(p[i].c-x);
nth_element(dis,dis+n-k,dis+n,cmp);
double s=0;
for(int i=0;i<n-k;i++)
{
s+=dis[i];
}
return s>=0;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%lld",&p[i].s);
for(int i=0;i<n;i++)
scanf("%lld",&p[i].c);
double l=0,r=1000001;
while(r-l>eps)
{
double mid=(r+l)/2;
if(check(mid)) l=mid;
else r=mid;
}
printf("%.6f\n",(r+l)/2);
return 0;
}