CF865D Buy Low Sell High
依靠堆完成贪心。
维护一个小根堆,扫描每一天的价格,如果之前的最小价格比它小就直接丢到堆里面去,如果比它大就累加答案并丢弃之前的最优解,然后把这个价格入队两次。
考虑一下为什么要入队两次,一次就相当于在这一天购买,一次代表以后反悔,答案累加之后就相当于在之前丢弃掉的地方买入在新的地方卖出,这样子一定能计算到最优答案。
时间复杂度$O(nlogn)$。
Code:
#include <cstdio> #include <cstring> #include <queue> using namespace std; typedef long long ll; const int N = 3e5 + 5; int n; ll a[N], ans = 0; struct Node { ll val; inline Node (ll v) { val = v; } friend bool operator < (const Node &x, const Node &y) { return x.val > y.val; } }; priority_queue <Node> Q; template <typename T> inline void read(T &X) { X = 0; char ch = 0; T op = 1; for(; ch > '9'|| ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } int main() { read(n); for(int i = 1; i <= n; i++) { read(a[i]); if(Q.empty()) Q.push(Node(a[i])); else { if(a[i] < Q.top().val) Q.push(Node(a[i])); else { ans += a[i] - Q.top().val; Q.pop(); Q.push(Node(a[i])), Q.push(Node(a[i])); } } } printf("%lld\n", ans); return 0; }
还有几个奶牛排序题等我理清楚之后再更。