子数组的最小值的贡献
非常经典的一道题,思想也很经典,核心点在于预处理出当前点为最小值时的辐射范围
int n = nums.size();
vector<int> left(n, -1);
vector<int> right(n, n);
// 维护递增栈
stack<int> stackUp;
for (int i = 0; i < n; ++i) {
// 栈顶对应值比当前值大,说明栈顶的右侧第一个最小值是i
while (!stackUp.empty() && nums[stackUp.top()] >= nums[i]) {
right[stackUp.top()] = i;
stackUp.pop();
}
// 此时如果栈非空,则栈顶值是i左侧的第一个最小值是栈顶
if (!stackUp.empty()) {
left[i] = stackUp.top();
}
// 更新递增栈
stackUp.emplace(i);
}
在得到了left和right数组后,可得当前点i的辐射范围是(left[i], right[i]), 注意是左开右开。
当前点i的最终贡献为nums[i] * (i - left[i]) * (right[i] - i)