题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6438
k值为是否已经卖出的标记,若k=1,说明在该天曾经卖出一件物品。然而因为从a买入,从b卖出,再从b买入,从c卖出和从a买入,从c卖出的结果是一样的。所以定义k值用来更新买卖的最优值。在优先队列中,如果两元素w值(当天价值)相同,则优先取k较大的元素。
优先队列存储每一天的价格,贪心对于第i天的价格,取前i-1天最小的价格与之比较。若比当前值大,就直接将a【i】加入优先队列(堆)中。否则弹出队首元素,答案加上a【i】-前i-1天的最小值。接下来向优先队列中加入两个a【i】,k值分别为0和1。应为排序时k大的排在前面,所以不用担心“从a买入,从b卖出,再从b买入,从c卖出”会被计算两次的情况。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
#define sqr(a) a*a
using namespace std;
LL a[100010];
struct node
{
LL w;
int k;
};
bool operator <(node a,node b)
{
if(a.w==b.w)
return a.k<b.k;
return a.w>b.w;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
priority_queue <node> run;
memset(a,0,sizeof a);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
LL ans=0,id=0;
for(int i=1;i<=n;i++)
{
node a1;
a1.w=a[i];
a1.k=0;
if(run.empty())
{
run.push(a1);
continue;
}
//printf("w=%lld k=%d\n",run.top().w,run.top().k);
if(run.top().w>=a[i])
run.push(a1);
else
{
node tem=run.top();
run.pop();
node temp;
temp.w=a[i];
temp.k=1;
if(tem.k==1)
{
run.push(temp);
temp.k=0;
run.push(temp);
ans+=a[i]-tem.w;
}
else
{
run.push(temp);
temp.k=0;
run.push(temp);
ans+=a[i]-tem.w;
id+=2;
}
}
}
printf("%lld %lld\n",ans,id);
}
return 0;
}