LC2542. 最大子序列的分数

给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,两者长度都是 n ,再给你一个正整数 k 。你必须从 nums1 中选一个长度为 k 的 子序列 对应的下标。

对于选择的下标 i0 ,i1 ,..., ik - 1 ,你的 分数 定义如下:

nums1 中下标对应元素求和,乘以 nums2 中下标对应元素的 最小值 。
用公示表示: (nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] , nums2[i1], ... ,nums2[ik - 1]) 。
请你返回 最大 可能的分数。

一个数组的 子序列 下标是集合 {0, 1, ..., n-1} 中删除若干元素得到的剩余集合,也可以不删除任何元素。

 

示例 1:

输入:nums1 = [1,3,3,2], nums2 = [2,1,3,4], k = 3
输出:12
解释:
四个可能的子序列分数为:
- 选择下标 0 ,1 和 2 ,得到分数 (1+3+3) * min(2,1,3) = 7 。
- 选择下标 0 ,1 和 3 ,得到分数 (1+3+2) * min(2,1,4) = 6 。
- 选择下标 0 ,2 和 3 ,得到分数 (1+3+2) * min(2,3,4) = 12 。
- 选择下标 1 ,2 和 3 ,得到分数 (3+3+2) * min(1,3,4) = 8 。
所以最大分数为 12 。
示例 2:

输入:nums1 = [4,2,3,1,1], nums2 = [7,5,10,9,6], k = 1
输出:30
解释:
选择下标 2 最优:nums1[2] * nums2[2] = 3 * 10 = 30 是最大可能分数。
 

提示:

n == nums1.length == nums2.length
1 <= n <= 105
0 <= nums1[i], nums2[j] <= 105
1 <= k <= n

分析:用set维护一个最大和,对nums2从大到小贪心,然后维护一个大小为k-1的nums1的最大和

class Solution {
    long long maxa =-1;
    struct node//要同时记录下标和对应值,所以用结构体存下每一个nums[i]
    {
        int x = 0;
        int p = 0;
        node(int x,int p)
        {
            this->x =x;
            this->p = p;
        }
    };
    vector<node> a; 
    multiset<int> s;
    multiset<int> s1;//用来维护最大和,用set的原因是set本身自带排序
    int min1 = 999999999;
public:
    long long maxScore(vector<int>& nums1, vector<int>& nums2, int k) {
        int n = nums1.size();
        if(k==1)//k等于1时要特判
        {
           for(int i = 0;i<n;i++)
           {
               maxa = max(maxa,(long long)nums1[i]*nums2[i]);
           }
           return maxa;
        }
        for(int i =0;i<n;i++)
        {
            a.push_back(node(nums2[i],i));
        }
        sort(a.begin(),a.end(),[](const node &a,const node &b){//对nums2排序
            return a.x>b.x;
        });
        long long temp = 0;
        for(int i = 0;i<k-1;i++)//前k-1个入set
        {
            s.insert(nums1[a[i].p]);
        }
        for(int i=k-1;i<n;i++)//因为nums1至少要取k-1个,所以直接从k-1开始
        {
            int p = k-1;
            auto j = --s.end();
            if(temp==0)
            {
            while(p--)
            {
                temp+=*j;
                s1.insert(*j);
                j--;
            }
            }
            temp+=nums1[a[i].p];
            maxa = max(maxa,temp*a[i].x);
            temp-=nums1[a[i].p];
            if(nums1[a[i].p]>*s1.begin())//更新最大和
            {
                temp-=*s1.begin();
                temp+=nums1[a[i].p];
                s1.erase(s1.begin());
                s1.insert(nums1[a[i].p]);
            }
        }
        return maxa;
    }
};

作者:remarkable-boy
链接:https://leetcode.cn/problems/maximum-subsequence-score/solution/by-remarkable-boy-cbz6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

posted @ 2023-03-19 21:05  remarkableboy  阅读(29)  评论(0编辑  收藏  举报