20181009noip HZ EZ 两校联考trade(优先队列,贪心)

题面戳这里

思路:

裸的,贪心。。。

考场上写了一个数据分治(70ptsDP,30pts线段树优化贪心,GG了后30分)

这道题其实很简单的

我们看图:

我们在A时刻买一个东西,在B时刻卖出去,我们可以赚到(6-5)=1元钱

我们在B时刻买一个东西,在C时刻卖出去,可以赚(7-6)=1元钱

我们在A时刻买一个东西,在C时刻卖出去,可以赚(7-5)=1元钱

我们会发现,在A时刻买入,在C时刻卖出答案等价于在A时刻买入,在B时刻卖出,再在B时刻买入,在C时刻卖出

这样的话我们在决策时就可以改变暴力的思路

我们假定一个东西买入

在后面某个时刻卖出

那么我们每次取价格最少的一个,和当前遍历到的数字大小作比较

如果当前价格比前面的买入价高,我们就卖出

同时将当前价格加入队列(便于未来反悔)并计算贡献

一直执行就是答案

(因为每次我只取堆顶判断是否操作,可以保证操作合法(每个点最多被执行一次操作,因为既买入又卖出等价于不进行操作))

代码:

#include<iostream>
#include<cstdio>
#include<queue>
#define rii register int i
#define rij regsiter int j
#define int long long
using namespace std;
int n,x;
struct wp{
    int val;
};
bool operator < (wp lk,wp kl)
{
    return lk.val>kl.val;
}
priority_queue<wp> q;
signed main()
{
    freopen("trade.in","r",stdin);
    freopen("trade.out","w",stdout);
    scanf("%lld",&n);
    int ans=0;
    for(rii=1;i<=n;i++)
    {
        scanf("%lld",&x);
        if(q.empty()==false)
        {
            int val=q.top().val;
            if(x>val)
            {
                ans+=x-val;
                q.pop();
                wp sr;
                sr.val=x;
                q.push(sr);
            }
        }
        wp sr;
        sr.val=x;
        q.push(sr);
    }
    cout<<ans;
}

猜你喜欢

转载自www.cnblogs.com/ztz11/p/9761766.html
hz
今日推荐