题意:给出n,和a[i]代表第i天东西的行价,问收益最大是多少,在此前提下交易次数最少是多少?
思路:
维护一个小根堆,每次将堆顶与a[i]比较,如果a[i]<min,直接把a[i]放入,如果a[i]>min,那么可以a[i]-min就暂且作为我当前的收益,当然这不一定是最优的方案,
考虑后面如果有a[j]>a[i],那我这个物品肯定在a[j]卖是最划算的。如果我在a[i]卖了后,再pusha[i]进小根堆,如果到了a[j]再卖的话这个过程中,你会发现ans先加了一个a[i]-min,又加了一个a[j]-a[i],那么其实对ans的贡献只有a[j]-min,就相当于min在a[j]这个点卖出。然后我们再考虑一下这样做是否对交易次数有影响,会发现如果这样交易次数会多加2,因此我们对中间商都需要标记一下。
#include<bits/stdc++.h> using namespace std; #define int long long const int maxn = 5e5+10; int n, a[maxn], ans = 0, cnt = 0; priority_queue<int, vector<int>, greater<int> > q; map<int, int> mp; signed main() { int t; cin >> t; while(t--) { while(!q.empty()) q.pop(); mp.clear(); ans = 0, cnt = 0; cin >> n; for(int i = 0; i< n; i++) cin >> a[i]; q.push(a[0]); for(int i = 1; i < n; i++){ int x = q.top(); if(x < a[i]) { ans += a[i]-x; cnt += 2; q.pop(); if(mp[x]) { mp[x]--;cnt-=2; } q.push(a[i]); mp[a[i]]++; } q.push(a[i]); } cout << ans << " " <<cnt <<endl; } }