2281. 巫师的总力量和

82 阅读3分钟

作为国王的统治者,你有一支巫师军队听你指挥。

给你一个下标从 0 开始的整数数组 strength ,其中 strength[i] 表示第 i 位巫师的力量值。对于连续的一组巫师(也就是这些巫师的力量值是 strength 的 子数组),总力量 定义为以下两个值的 乘积 :

  • 巫师中 最弱 的能力值。
  • 组中所有巫师的个人力量值 之和 。

请你返回 所有 巫师组的  力量之和。由于答案可能很大,请将答案对 109 + 7 取余 后返回。

子数组 是一个数组里 非空 连续子序列。

示例 1:

输入: strength = [1,3,1,2]
输出: 44
解释: 以下是所有连续巫师组:
- [1,3,1,2][1] ,总力量值为 min([1]) * sum([1]) = 1 * 1 = 1
- [1,3,1,2][3] ,总力量值为 min([3]) * sum([3]) = 3 * 3 = 9
- [1,3,1,2][1] ,总力量值为 min([1]) * sum([1]) = 1 * 1 = 1
- [1,3,1,2][2] ,总力量值为 min([2]) * sum([2]) = 2 * 2 = 4
- [1,3,1,2][1,3] ,总力量值为 min([1,3]) * sum([1,3]) = 1 * 4 = 4
- [1,3,1,2][3,1] ,总力量值为 min([3,1]) * sum([3,1]) = 1 * 4 = 4
- [1,3,1,2][1,2] ,总力量值为 min([1,2]) * sum([1,2]) = 1 * 3 = 3
- [1,3,1,2][1,3,1] ,总力量值为 min([1,3,1]) * sum([1,3,1]) = 1 * 5 = 5
- [1,3,1,2][3,1,2] ,总力量值为 min([3,1,2]) * sum([3,1,2]) = 1 * 6 = 6
- [1,3,1,2][1,3,1,2] ,总力量值为 min([1,3,1,2]) * sum([1,3,1,2]) = 1 * 7 = 7
所有力量值之和为 1 + 9 + 1 + 4 + 4 + 4 + 3 + 5 + 6 + 7 = 44

示例 2:

输入: strength = [5,4,6]
输出: 213
解释: 以下是所有连续巫师组:
- [5,4,6][5] ,总力量值为 min([5]) * sum([5]) = 5 * 5 = 25
- [5,4,6][4] ,总力量值为 min([4]) * sum([4]) = 4 * 4 = 16
- [5,4,6][6] ,总力量值为 min([6]) * sum([6]) = 6 * 6 = 36
- [5,4,6][5,4] ,总力量值为 min([5,4]) * sum([5,4]) = 4 * 9 = 36
- [5,4,6][4,6] ,总力量值为 min([4,6]) * sum([4,6]) = 4 * 10 = 40
- [5,4,6][5,4,6] ,总力量值为 min([5,4,6]) * sum([5,4,6]) = 4 * 15 = 60
所有力量值之和为 25 + 16 + 36 + 36 + 40 + 60 = 213

提示:

  • 1 <= strength.length <= 105
  • 1 <= strength[i] <= 109

题解:

/**
 * @param {number[]} strength
 * @return {number}
 */
var totalStrength = function (strength) {
    let mod = BigInt(1e9 + 7)
    let n = strength.length;
    let left = new Array(n).fill(-1)
    let right = new Array(n).fill(n)
    const st = []
    st.push(-1)
    for (let i = 0; i < n; i++) {
        while (st.length && strength[st[st.length - 1]] >= strength[i]) {
            right[st.pop()] = i
        }
        left[i] = st[st.length - 1]
        st.push(i)
    }
    let s = 0n; // 前缀和
    let ss = [0n, 0n]; // 前缀和的前缀和
    for (let i = 1; i <= n; ++i) {
        s += BigInt(strength[i - 1])
        // 注意取模后,下面计算两个 ss 相减,结果可能为负
        ss[i + 1] = BigInt((ss[i] + s) % mod);
    }

    let ans = 0n;
    for (let i = 0; i < n; ++i) {
        let l = left[i] + 1, r = right[i] - 1; // [l,r] 左闭右闭
        let tot = (BigInt(i - l + 1) * (ss[r + 2] - ss[i + 1]) - 
            BigInt(r - i + 1) * (ss[i + 1] - ss[l])) % mod;
        ans = (ans + BigInt(strength[i]) * tot) % mod; // 累加贡献
    }
    return BigInt((ans + mod) % mod); // 防止算出负数
};

来源:力扣(LeetCode)

链接:leetcode.cn/problems/su…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。