【HIHOCODER 1604】股票价格II(堆)

描述


小Hi最近在关注股票,为了计算股票可能的盈利,他获取了一只股票最近N天的价格A1~AN。
在小Hi的策略中,每天可以在下列三种操作中选取一种:
1.什么也不做;
2.按照当天的价格买进一个单位的股票;
3.按照当天的价格卖出部分或所有股票。
现在小Hi希望能够知道,如果在N天前手中持有的股票数为0,并且假设拥有无限的金钱,在这N天结束能够获得的最大利润是多少?

输入


第一行包含一个整数N。
第二行包含N个整数,A1, A2, ... AN。
对于30%的数据, 1 ≤ N ≤ 103
对于100%的数据,1 ≤ N ≤ 106, 1 ≤ Ai ≤ 100

输出


输出这N天结束能够获得的最大利润

样例输入

5
1 2 3 4 5

样例输出

10

题解


观察到最优方案是每次选择价格最大时卖出。
维护一个区间,用大根堆维护股票价格及其位置,只要某个当前最大在这个区间内,就计算其可获利润:
(value imes (index-l)-sum(index-1)+sum(l-1))
总时间为(O(nlogn))

#include <vector>
#include <queue>
#include <cstdio>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define inf 1000000000
#define PI acos(-1)
#define bug puts("here")
#define REP(i,x,n) for(int i=x;i<=n;i++)
#define DEP(i,n,x) for(int i=n;i>=x;i--)
#define mem(a,x) memset(a,x,sizeof(a))
typedef unsigned long long ull;
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void Out(int a){
    if(a<0) putchar('-'),a=-a;
    if(a>=10) Out(a/10);
    putchar(a%10+'0');
}
const int N=1000000+5;
int a[N];
ll sum[N],b[N];
struct node{
    int v,id;
    bool operator < (const node & an) const{
         if(v==an.v) return id<an.id;
         return  v<an.v;
    }
};
priority_queue<node> que;
int main(){
    int n=read();
    REP(i,1,n) a[i]=read(),sum[i]=sum[i-1]+a[i];
    REP(i,1,n){
        que.push(node{a[i],i});
    }
    int l=1,r=n;node x;
    ll ans=0;
    while(l<=r&&!que.empty()){
        x=que.top();que.pop();
        if(x.id>=l){
            ans+=x.v*(x.id-l)-sum[x.id-1]+sum[l-1];
            l=x.id+1;
        }
    }
    printf("%lld
",ans);
    return 0;
}