• Codeforces #657 Div2C choosing flowers


    看错时间导致错过一场比赛......

    题意,有m种无限多的物品,有两个价值(a[i],b[i]),若选x[i](x[i] >= 1)个,则能获得(a[i] + (x[i] - 1) * b[i])的价值(若不选则价值为0)

    求选出n个,使得价值最大.m<=1e5,n,a[i],b[i]<=1e9;

    分析:这个数据范围大概就是要贪心了,然后考虑怎么贪.我们发现,若只选一个,实质上只有a[i]在起作用,只有选两个以上,b[i]才有影响.可以猜测出要么所有的都只选一个,要么只有一种物品选超过一个.

    证明如下:

    设第i个物品选的个数为cnt[i],对于任意的i,j,若cnt[i],cnt[j]>=1,设b[i] >= b[j],则显然如果接下来还有若干个选择机会,选第i个物品一定比选j个物品优,因为既然都选了一次后,价值就与a[i]无关了,所以选择的贡献b[i] >= b[j].

    所以我们可以枚举哪种物品要选超过一次.显然我们如果枚举到第i个物品,可以先钦定x[i]  = n,即n个物品全选x[i],然后对于(j != i && a[j] > b[i]),再反悔一次,选择a[j],这个过程可以先排序,然后二分大于b[i]的a[j],前缀和加一下即可

    记得特判所有物品都只选一种的情况

    时间复杂度(nlogn)

    (挺简单一道题,不知道为什么只有1000来个人过)

    /*C. Choosing flowers*/ 
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn = 1e6 + 10;
    #define ll long long
    struct Num{
        int fir,sec,id;
        bool operator < (Num A){
            return fir < A.fir; 
        }
    }a[maxn];
    ll sum[maxn];
    int n,m;
    int read(){
        char ch = getchar();
        int x = 0;
        while(ch < '0' || ch > '9')        ch = getchar();
        while(ch >= '0' && ch <= '9')    x = x * 10 + ch - 48,ch = getchar();
        return x;
    }
    int get(int x){
        int l = 1,r = m;
        int ans = 0;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(a[mid].fir <= x){
                l = mid + 1;
                ans = mid;
            }
            else{
                r = mid - 1;
            }
        } 
        return m - ans;
    }
    int main()
    {
        int t = read();
        while(t--){
            n = read(),m = read();
            for(int i = 1; i <= m; ++i){
                a[i].fir = read();
                a[i].sec = read();
                a[i].id = i;
            }
            sort(a+1,a+m+1);
            for(int i = 1; i <= m; ++i)
                sum[i] = sum[i-1] + a[i].fir;
            ll ans = 0;
            if(n <= m){
                ans = sum[m] - sum[m - n];
            }
            for(int i = 1; i <= m; ++i){
                int k = get(a[i].sec);
                ll res = sum[m] - sum[m - k];
                if(a[i].fir <= a[i].sec){
                    k++;
                    res += a[i].fir;
                }
                if(k >= n)    continue;
                else{
                    res += 1ll * (n - k) * a[i].sec;
                    ans = max(ans,res);
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    几种asp.net页面缓存的做法
    [转载]如果你也想做一个Pinterest网站
    Oracle支持的字符函数和它们的Microsoft SQL Server等价函数
    使用OLEDB读取不同版本Excel数据的连接字符串设置
    SQLServer和Oracle的常用函数对比
    [转载] 简易Pinterest/瀑布流布局
    C# WinForm 实现控件可拖拽
    【转载】Highcharts使用指南
    RBAC开发技术
    一个比较好的winform内嵌excel插件
  • 原文地址:https://www.cnblogs.com/y-dove/p/13341029.html
Copyright © 2020-2023  润新知