zoukankan      html  css  js  c++  java
  • CF521D

    CF521D

    有 k 个正整数 a1…k​。
    有 n 个操作,每个操作给定正整数 b,有三种可能:将 ai​ 赋值为 b,将 ai​ 加上 b,将 ai​ 乘以 b。
    你可以从 n 个操作中选择最多 m 个操作,并按照一定顺序执行。
    你的目标是最大化这些 ai​ 的乘积。
    k,n ≤ 1e5。
    输出操作个数和操作顺序

    =============================================================

    对任意一个数的乘法操作都可以直接对整体做贡献,所以将赋值和加法转化为乘法进行比较每个操作对答案的贡献

    其它两个操作用贪心考虑,对于同一个数,最多使用一次赋值操作,且该操作需满足赋值后大于原值;而对于加法来说,在尽量少的次数中尽量保证加了尽量大的数。

    将赋值转化为加法运算,再将所有加法运算进行比较,同一个数加得多的先操作

    然后把加法转化为乘法操作,(原理 :a + b = a * ((a + b) / a))。

    最后的操作序列就全是乘法操作了,只需取前 m 次操作即可

    code

    typedef pair <int,int> PII;
    typedef pair <long double,int> PLI
    PII as[N];
    vector <PII> add[N];
    vector <PLI> mul;
     
    bool cmp(PII a,PII b){return t[a.second] < t[b.second];}
     
    int main()
    {
        cin >> n >> k >> m;
        for(int i = 1;i <= n;i ++) cin >> a[i];
        for(int i = 1;i <= k;i ++)
        {
            int x,y,z;
            cin >> x >> y >> z;
            t[i] = x;//保存操作顺序,最后先输出 操作1 , 2 , 3; 
            if(x == 1) as[y] = max(as[y],{z,i});
            if(x == 2) add[y].push_back({z,i});
            if(x == 3) mul.push_back({z,i});
        }
        for(int i = 1;i <= n;i ++)
            if(as[i].first > a[i])
                add[i].push_back({as[i].first - a[i],as[i].second});//将所有赋值操作转化为加法操作 
        for(int i = 1;i <= n;i ++)
        {
            sort(add[i].begin(),add[i].end());
            reverse(add[i].begin(),add[i].end());
            //对于加法来说,从大数开始加更优 
            long long v = a[i];
            for(int j = 0;j < add[i].size();j ++)
            {
                PII p = add[i][j];
                mul.push_back({1.0L * (v + p.first) / v,p.second});
                v += p.first;//要记录上一次加完后值变为多少,这样才能转化为乘法 
            }
        }
        sort(mul.begin(),mul.end());
        reverse(mul.begin(),mul.end());
        int x = min(m,(int)mul.size());
        sort(mul.begin(),mul.begin() + x,cmp);//保证赋值和加法操作在先 
        cout << x << endl;
        for(int i = 0;i < x;i ++)
            cout << mul[i].second << ' ';
        return 0;
    }
    

    这里贴出思路和代码来源

  • 相关阅读:
    p2394 精度题
    线性筛素数
    poj3468 线段树的懒惰标记
    逆元
    2018 Multi-University Training Contest 2
    2018 Multi-University Training Contest 1
    判断素数遇到的问题
    Mergeable Stack(链表实现栈)
    组合数
    poj2594 机器人寻找宝藏(最小路径覆盖)
  • 原文地址:https://www.cnblogs.com/xy0313/p/14072883.html
Copyright © 2011-2022 走看看