子序列的最大优雅度

给你一个长度为 n 的二维整数数组 items 和一个整数 k 。
items[i] = [profiti, categoryi],其中 profiti 和 categoryi 分别表示第 i 个项目的利润和类别
现定义 items 的 子序列的优雅度 可以用 total_profit + distinct_categories2 计算
从 items 所有长度为 k 的子序列中,找出最大优雅度

1. 反悔贪心

结果的值受利润和种类两个维度影响,我们可以先考虑一个维度,然后再对另一个维度进行贪心替换
先按利润从大到小排序,贪心取前k个值,并且记录类别和重复类别的利润
后面对可以增加种类的值进行替换,并且动态规划记录更新当下最大值

class Solution {
public:
    long long findMaximumElegance(vector<vector<int>>& items, int k) {
        //只能遍历一次,要么贪心、要么排序贪心
        int n = items.size();
        long long res = 0;
        long long total = 0;
        //先按利润从大到小排序
        sort(items.begin(), items.end(), [](const auto &a, const auto &b) {
            return a[0] > b[0];
        });
        unordered_set<int> vis;
        stack<int> duplicate;//重复类别的利润
        for(int i=0;i<n;i++){ //只需遍历一次
            int profit = items[i][0]; int category = items[i][1];
            if(i<k){//先贪心选中前k个
                total += profit;//计算总利润
                if(vis.count(category))
                    duplicate.push(profit);//非第一个的重复类别利润,后面用作替换
                vis.insert(category);
            }
            else if(!duplicate.empty()&&!vis.count(category)){//对于候选替换数,如果存在可替换的重复类别,且当前类别没出现过
                //进行替换
                vis.insert(category);
                total += profit - duplicate.top();
                duplicate.pop();
            }
            //动态规划,记录最大值
            res = max(res, total + (long long)vis.size()*(long long)vis.size());
        }
        return res;
    }
};
posted @ 2023-08-10 15:37  失控D大白兔  阅读(27)  评论(0编辑  收藏  举报