题面戳这里
思路:
裸的,贪心。。。
考场上写了一个数据分治(70ptsDP,30pts线段树优化贪心,GG了后30分)
这道题其实很简单的
我们看图:
我们在A时刻买一个东西,在B时刻卖出去,我们可以赚到(6-5)=1元钱
我们在B时刻买一个东西,在C时刻卖出去,可以赚(7-6)=1元钱
我们在A时刻买一个东西,在C时刻卖出去,可以赚(7-5)=1元钱
我们会发现,在A时刻买入,在C时刻卖出答案等价于在A时刻买入,在B时刻卖出,再在B时刻买入,在C时刻卖出
这样的话我们在决策时就可以改变暴力的思路
我们假定一个东西买入
在后面某个时刻卖出
那么我们每次取价格最少的一个,和当前遍历到的数字大小作比较
如果当前价格比前面的买入价高,我们就卖出
同时将当前价格加入队列(便于未来反悔)并计算贡献
一直执行就是答案
(因为每次我只取堆顶判断是否操作,可以保证操作合法(每个点最多被执行一次操作,因为既买入又卖出等价于不进行操作))
代码:
#include<iostream> #include<cstdio> #include<queue> #define rii register int i #define rij regsiter int j #define int long long using namespace std; int n,x; struct wp{ int val; }; bool operator < (wp lk,wp kl) { return lk.val>kl.val; } priority_queue<wp> q; signed main() { freopen("trade.in","r",stdin); freopen("trade.out","w",stdout); scanf("%lld",&n); int ans=0; for(rii=1;i<=n;i++) { scanf("%lld",&x); if(q.empty()==false) { int val=q.top().val; if(x>val) { ans+=x-val; q.pop(); wp sr; sr.val=x; q.push(sr); } } wp sr; sr.val=x; q.push(sr); } cout<<ans; }