• POJ


    包含一些ai和bi的集用S来表示,x = max(sigma(ai)/sigma(bi),i 属于S) ,k 表示S的大小,k= |S|。

    x和k之间具有单调性。k0 < k1 → x0 ≥ x1。单调性对x(k)的反函数k(x)也成立。现在的问题是k已经给出,

    那么猜测一个x,通过和sigma(ai)/sigma(bi) 作差得到大小关系以便收敛区间。

    要求x可以做一点变形sigma(ai)/sigma(bi) - k*x → sigma(ai - x*b),x是max值,和一个常数作差以后也是最大的,

    因此选取前k大元素ai - x*b求和就可以得到差值。

    (还有一种很迷的迭代法也可以收敛

    /*********************************************************
    *            ------------------                          *
    *   author AbyssalFish                                   *
    **********************************************************/
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<cmath>
    #include<numeric>
    using namespace std;
    
    const int maxn = 1e5;
    int n, k;
    
    struct Query
    {
        int v,w;
        double key;
    }q[maxn];
    
    int r[maxn];
    
    struct cmp
    {
        bool operator()(int a,int b){ return q[a].key > q[b].key; }
    };
    
    double cal(double x)
    {
        for(int i = 0; i < n; i++){
            q[r[i]].key =  q[r[i]].v-x*q[r[i]].w;
        }
        nth_element(r,r+k,r+n,cmp());
        double re = 0;
        for(int i = 0; i < k; i++){
            re += q[r[i]].key;
        }
        return re;
    }
    
    const double eps = 1e-11;
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        while(~scanf("%d%d",&n,&k)){
            double lb = 0, ub = 0, md, re;
            for(int i = 0; i < n; i++){
                scanf("%d%d",&q[i].v,&q[i].w);
                r[i] = i;
                ub = max(ub,(double)q[i].v/q[i].w);
            }
    
            for(int i = 100; i--;){
                md = (lb+ub)/2;
                re = cal(md);
                if(re > eps) lb = md;
                else if(re < -eps) ub = md;
                else break;
            }
            k--;
            for(int i = 0; i < k; i++){
                printf("%d ",r[i]+1);
            }
            printf("%d
    ",r[k]+1);
        }
    
        return 0;
    }
  • 相关阅读:
    图论算法——最短路系列
    1126 数字统计 2010年NOIP全国联赛普及组
    JavaEE Tutorials (10)
    情书
    洛谷 P1171 售货员的难题
    洛谷 P1769 淘汰赛制_NOI导刊2010提高(01)
    洛谷 P1858 多人背包
    HDU 2639 Bone Collector II
    国庆 day 6 下午
    国庆 day 6 上午
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4969716.html
Copyright © 2020-2023  润新知