Dropping tests

OJ: POJ

题目 ID: 2976

标签: 01分数规划

日期: 2026-01-05 15:01

题目解析

  • 二分性: 如果分数 x 可以达到, 那么query_max_sum(x) >=0 $ 成立,则分数 $x_i < x 都可以成立,我们要使得x尽可能的大
  • 答案范围: [0,1][0,1]

代码

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github : https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * date: 2026-01-05 15:28:43
 */
#include <bits/stdc++.h>
using namespace std;
typedef  long long ll;
typedef  unsigned long long ull;

const int maxn = 2e6+5;
int n,k;
int a[maxn];
int b[maxn];
double v[maxn]; // v[i] = a[i] - x * b[i] 

double _sum(double x) {
    for(int i = 1;i <= n ;++i ) // i: 1->n
    {
        v[i] = a[i] -  x * b[i];
    }
    std::sort(v+1,v+1+n);

    // 这里是贪心, 选的越少越好, 哪就选 n-k个
    double s = 0;
    for(int i = n;i >k;--i ) // i: 1->n
        s+= v[i];
    return s;
}

//检查pos位置的值是否符合要求
bool check(double mid){
    return _sum(mid) >= 0;
}



signed main () {
    ios::sync_with_stdio(false); cin.tie(0);
    while (1) {
        std::cin >> n >> k;
        if( n == 0 &&k == 0) break;
        for(int i = 1;i <= n ;++i ) // i: 1->n
            std::cin >> a[i];
        for(int i = 1;i <= n ;++i ) // i: 1->n
            std::cin >> b[i];

        // 枚举分数
        double l = 0 , r = 1;

        //100 次 应该可以了
        for(int i = 0 ;i < 100 ;i++)
        {
            double mid = (l+r) / 2;
            if( check(mid)) 
                l = mid;
            else
                r = mid;

        }
        std::cout << (int)(l*100 + 0.5) << "\n";
        
    }
    
    return 0;
}