【JZOJ4835】【GDOI2017模拟10.31】量化交易

题目描述

这里写图片描述

数据范围

这里写图片描述

解法

贪心;
从左往右枚举,设枚举到元素为x,并维护一个堆:
设此时堆顶元素为y,
如果x大于y,那么x可以与y产生差价,立即将差价贡献给答案。
如果y之前已经和其他元素z产生过差价了,那么y显然可以省出来以得到最优答案,因为x-z=x-y+y-z;
否则,把y移出堆。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define sqr(x) ((x)*(x))
#define ln(x,y) ll(log(x)/log(y))
using namespace std;
const char* fin="trade.in";
const char* fout="trade.out";
const ll inf=0x7fffffff;
const ll maxn=100008;
ll n,i,j,k,v=0,ans,t;
ll a[maxn],son[maxn];
struct dui{
    ll data[maxn],num;
    void init(){
        memset(data,0,sizeof(data));
        num=0;
    }
    dui(){
        init();
    }
    bool cmp(ll v,ll u){
        return a[v]<=a[u];
    }
    void up(ll x){
        while (x>1 && cmp(data[x],data[x/2])) swap(data[x],data[x/2]),x=x/2;
    }
    void down(ll x){
        while (x*2<=num && cmp(data[x*2],data[x]) || x*2+1<=num && cmp(data[x*2+1],data[x])){
            if (x*2+1>num || cmp(data[x*2],data[x*2+1])){
                swap(data[x],data[x*2]);
                x=x*2;
            }else{
                swap(data[x],data[x*2+1]);
                x=x*2+1;
            }
        }
    }
    void push(ll v){
        data[++num]=v;
        up(num);
    }
    void pull(){
        swap(data[1],data[num--]);
        down(1);
    }
    ll top(){
        if (num) return data[1];
        else return 0;
    }
}d;
ll read(){
    ll x=0,y=0;
    char ch=getchar();
    while (ch<'0' || ch>'9') {
        ch=getchar();
        y++;
        if (y==10) return -1;
    }
    while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;
}
int main(){
    freopen(fin,"r",stdin);
    freopen(fout,"w",stdout);
    while (1){
        n=read();
        if (n==-1) break;
        ans=0;
        t++;
        d.init();
        for (i=1;i<=n;i++) a[i]=read();
        memset(son,0,sizeof(son));
        for (i=1;i<=n;i++){
            if (d.top()){
                j=d.top();
                if (a[i]>a[j]){
                    ans+=a[i]-a[j];
                    if (son[j]){
                        son[j]=0;
                        son[i]=j;
                    }else {
                        d.pull();
                        son[i]=j;
                    }
                }
            }
            d.push(i);
        }
        printf("Case #%lld: %lld
",t,ans);
    }
    return 0;
}

启发

有关策略的问题可以考虑贪心;
贪心正着推,可以使用数据结构帮助贪心找到更优的解。

原文地址:https://www.cnblogs.com/hiweibolu/p/6714859.html