HackerRank–Stock Maximize
题目描述
给定N天的股票价格。每一天用户可以选择买入一股,或者卖出自己拥有的任意股,或者什么交易都不做。求可以获得的最大的利润。
分析
目标很直观,希望找到一个最大价格的日子卖掉之前买进的所有股票,所以需要记录当前股票价格的所有极大值。
如果当前价格大于之前的极大值,就应该更新极大值为今天的价格,并放弃在之前那一天卖出,这一过程可能会超过多个之前的极大值,那么之前的极大值都可以也应该被舍弃;如果当前价格小于之前的值,应当等待后面的更高价格来判断当前值的去留。
我们只需要记录极大值出现的天数是第几天,然后每次把两个极大值之间的价格用后面的极大值都减去再求和即可。
需要用数组存储所有的价格,不能用常数空间,然后可以用栈来维护当前极大值,因为只需要从末端考虑。
数据范围
天数 N 可以有 50000,股票价格是 1 到 100000,int32 会溢出,结果要用 long long /int64。
实现
#include <stack>
#include <vector>
#include <iostream>
using namespace std;
int main(){
int T;
cin >> T;
int N;
for (int tt = 0; tt < T; ++tt) {
cin >> N;
vector<int> ve(N);
int p;
for (int i = 0; i < N; ++i)
cin >> ve[i];
stack<int> st;
st.push(0);
for (int i = 1; i < N; i++) {
int last_max_i;
while (!st.empty()) {
last_max_i = st.top();
if (ve[i] > ve[last_max_i]) {
st.pop();
} else {
break;
}
}
st.push(i);
}
long long ans = 0;
while (!st.empty()) {
int sale_day = st.top();
st.pop();
int last_sale_day = st.empty() ? -1 : st.top();
for (int j = sale_day - 1; j > last_sale_day; j--) {
ans += ve[sale_day] - ve[j];
}
}
cout << ans << endl;
}
return 0;
}