题意:
给出n天,每天可以买进或者卖出或者不买不卖,价格是这一天的权值,问最多利润是多少,如果利润相同的有多种,取操作数最小的那种。输出最多利润与操作数。
思路:
这道题队友似乎最后想出来了啊?可是来不及写了…
用小顶堆维护。
如果当前输入为x,当堆为空或者堆顶元素大于等于x时,把x放入堆中(因为如果利润相同要操作数最小,所以等于也要放入堆中,而不是买卖)。
否则删除堆顶元素,将x在堆中放两遍,
- 抵消这一次的卖出,用后面更大的数来换掉它;
- 把这一次当成买入。
如何统计操作数呢?
因为会出现抵消的情况,那么抵消这里应该不能算,所以开个vis数组标记一下。
又因为要使操作数最小,所以抵消的时候如果有相同数值,就随便抵消哪一个,而不是一定要上一个出现卖的那个地方。所以数组下标是权值。
手动模拟一下就会发现很有道理。
代码:
typedef long long ll;
map<ll,int>vis;
int main()
{
int t,n;
ll x;
scanf("%d",&t);
while(t--)
{
priority_queue<ll,vector<ll>,greater<ll> >q;
vis.clear();
scanf("%d",&n);
ll ans=0;
int num=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
if(q.empty()||q.top()>=x)
q.push(x);
else
{
ans+=x-q.top();
if(vis[q.top()])
vis[q.top()]--;
else num+=2;
q.pop();
vis[x]++;
q.push(x);
q.push(x);
}
}
printf("%lld %d\n",ans,num);
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!