HDU 6438 网络赛 Buy and Resell(贪心 + 优先队列)题解
思路:维护一个递增队列,如果当天的w比队首大,那么我们给收益增加 w - q.top(),这里的意思可以理解为w对总收益的贡献而不是真正获利的具体数额,这样我们就能求出最大收益。注意一下,如果w对收益有贡献,你会发现w入队了两次,这是因为这里的w可能会有两种可能:
1.当做中间价/最终卖出价
2.买入价
所以我们入队两个w,如果w是买入价,那么其中一个w作为中间价势必弹出,另一个w作为买入价;如果w是最终卖出价,那么两个w会一直待在队列里。
计算总数很简单,用map[i]表示以i为中间价还存在多少个,如果是中间价就不加数量。
记得开long long orz
参考:CodeForces - 867E Buy Low Sell High 贪心 + 优先队列
代码:
#include<cstdio> #include<queue> #include<map> #include<algorithm> #include<iostream> #define ll long long using namespace std; priority_queue<int, vector<int>, greater<int> > q; map<int, int> st; int main(){ int T, n, w; scanf("%d", &T); while(T--){ st.clear(); while(!q.empty()) q.pop(); scanf("%d", &n); ll num = 0, ans = 0; for(int i = 0; i < n; i++){ scanf("%d", &w); if(!q.empty() && q.top() < w){ if(st[q.top()] > 0){ st[q.top()]--; } else{ num += 2; } st[w]++; ans += w - q.top(); q.pop(); q.push(w); } q.push(w); } printf("%lld %lld\n",ans, num); } return 0; }