Title

LeetCode每日一题2025-10-11-LC3186-施咒的最大伤害

3186-施咒的最大伤害

思路

题目大意是:选出一个子集,这个子集需要满足一个要求:子集中元素相互之间的差值不能是1和2,目标求最大子集和

  • 直接考虑一个元素应不应该被选上既要考虑比它小的,又要考虑比它大的,比较麻烦,我们直接从小往大考虑,加入一个数的时候就只用考虑比它小的数就可以了,所以我们先把数组排个序

  • 接着我们考虑每一个元素,对于元素\(a_i\),如果\(a_{i - 1} = a_i\),那么\(a_i\)肯定跟在\(a_{i - 1}\)的后面才能保证此时是在选上\(a_{i}\)的情况下的最优解

  • 如果\(a_{i - 1} \neq a_{i}\),此时我们在一个合法范围内\((a_i - a_j \geq 3)\)时找一个最大值就好,因为我们已经提前排过序了,所以此时可用用二分查找, 找最大值就理所当然地维护一个前缀最大值就好了

那么这个题目我们就维护两个数组就好了
\(premax[i]\) : 前\(i\)个元素取值的最大值
\(dp[i]\) : 前\(i\)个元素,选上元素\(i\)时的最大值

\[premax[i] = \begin{cases} power[0] &i = 0\\ max(premax[i - 1], \space dp[i]) &i > 0 \end{cases} \]

\[dp[i] = \begin{cases} power[0] &i = 0\\ dp[i - 1] + power[i] &power[i] = power[i - 1]\\ Max_{j = 0}^{i - 1}dp[j] + power[i] &power[i] \neq power[i - 1] \end{cases} \]

代码

using lli = long long;
class Solution {
public:
    lli maximumTotalDamage(std::vector<int>& power) 
    {
        int n = power.size();
        std::vector<lli> premax(n, 0);
        std::vector<lli> dp(n, 0);
        std::sort(power.begin(), power.end());
        dp[0] = power[0];
        premax[0] = dp[0];
        for (int i = 1; i < n; i++)
        {
            if (power[i] == power[i - 1])
            {
                dp[i] = dp[i - 1] + power[i];
            }
            else
            {
                int l = -1, r = i;
                while(l + 1 < r)
                {
                    int mid = (l + r) >> 1;
                    if (power[i] - power[mid] >= 3)
                    {
                        l = mid;
                    }
                    else
                    {
                        r = mid;
                    }
                }
                if (l == -1)
                {
                    dp[i] = power[i];
                }
                else
                {
                    dp[i] = premax[l] + power[i];
                }
            }
            premax[i] = std::max(premax[i - 1], dp[i]);
        }
        lli ans = 0;
        for (int i = 0; i < n; i++) ans = std::max(ans, dp[i]);
        return ans;
    }
};
posted @ 2025-10-11 10:29  栗悟饭与龟功気波  阅读(4)  评论(0)    收藏  举报