在线评测链接
题目描述
给一定一个数组,每个位置的美好值是离该位置最近的且下标小于该位置,值小于等于该值的值,若没有则为0。求所有位置的美好值总和。
输入描述
第一行一个整数 n n n,表示数组长度。 ( 1 ≤ n ≤ 1 0 5 ) (1 \leq n \leq 10^5) (1≤n≤105)
接一行下来 n n n个整数,表示该数组。 ( 1 ≤ a [ i ] ≤ 1 0 5 ) (1 \leq a[i] \leq 10^5) (1≤a[i]≤105)
输出描述
输出一个整数,表示美好值的总和
样例
输入
5
2 3 4 1 5
输出
6
说明
0号位置前面没有值,美好值为0
1号位置前面最近小于等于的值为2,美好值为2
2号位置前面最近小于等于的值为3,美好值为3
3号位置前面没有小于等于该值的数,美好值为0
4号位置前面最近小于等于的值为1,美好值为1
总的美好值为 2 + 3 + 1 = 6 2+3+1=6 2+3+1=6
思路:单调栈
本题题目意思可以转为找到左边第一个比它小的数,因此可以使用单调栈来求解该问题
类似题目:503. 下一个更大元素 II - 力扣(LeetCode)
时间复杂度
O ( n ) O(n) O(n)
代码
C++
#include<bits/stdc++.h>
using namespace std;
int n,x;
int main(){
cin>>n;
long long res=0;
stack<int>stk;
for(int i=0;i<n;i++){
cin>>x;
while(stk.size()&&stk.top()>x)stk.pop();
if(stk.size())res+=stk.top();
stk.push(x);
}
cout<<res<<endl;
return 0;
}
python代码
n = int(input())
nums = list(map(int, input().split()))
nums.reverse()
stack = []
ans = 0
for i, num in enumerate(nums):
while len(stack) > 0 and num <= nums[stack[-1]]:
stack.pop()
ans += num
stack.append(i)
print(ans)
Java代码
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] a = new int[n];
for(int i = 0;i<n;i++){
a[i] = in.nextInt();
}
long res = 0;
Deque<Integer> stack = new LinkedList<>();
for(int i = n-1;i>=0;i--){
while(!stack.isEmpty() && a[i] <= stack.peek()){
stack.pop();
res += a[i];
}
stack.push(a[i]);
}
System.out.println(res);
}
}