Buy and Resell hdu-6438
题意:给出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;
}
}
查看12道真题和解析
