• P3545 [POI2012]HURWarehouse Store


    题目描述

    洛谷

    \(n\) 天。第 \(i\) 天上午会进货 \(A_i\) 件商品,中午的时候会有顾客需要购买 \(B_i\) 件商品,可以选择满足顾客的要求,或是无视掉他。

    如果要满足顾客的需求,就必须要有足够的库存。问最多能够满足多少个顾客的需求。

    数据范围: 对于100%的数据,\(1\leq n\leq 250000,0\leq ai,bi\leq 10^9\)

    这是一道很经典的贪心题

    贪心策略:当能满足当前所有人时满足当前所有人。

    但当不能满足时,就会出现错误。

    那我们怎么保证贪心的正确行呢?

    当我们不能满足时,我们可以看看前面的人,看看满足这个人是不是更优。

    假如,当前这个人要比前面买的最多的人都要多,那我们可以不买给

    这个人,以此来留下更多的商品,满足剩下的人。

    如果比前面买的最多的人都要少,说明满足这个人要更优,

    因为他可以剩下更多的商品,来满足剩下的人。

    那我们就可以考虑维护一个大跟堆,每次把人的序号和他买的商品数

    加入堆中,然后按照上述方法维护就行了。

    几个注意的点
    1. 在删除大根堆堆顶时,一定要判断这个堆是否为空。否则就会疯狂RE

    2. 一定要开 long long(不开long long见祖宗

    code:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define LL long long
    using namespace std;
    LL n,ans;
    LL a[300010],b[300010];
    bool vis[300010];
    priority_queue<pair<LL,int>, vector< pair<LL,int> > >q;//维护一个大根堆
    int main()
    {
    	scanf("%lld",&n); LL rest = 0;
    	for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
    	for(int i = 1; i <= n; i++) scanf("%lld",&b[i]);
    	for(int i = 1; i <= n; i++)
    	{
    		rest += a[i];
    		if(b[i] <= rest)//剩下的商品数,要比这个人买的要多,则可以满足
    		{
    			ans++;
    			q.push(make_pair(b[i],i));
    			rest -= b[i];//rest存剩下的商品数
    			vis[i] = 1;
    		}
    		else if(!q.empty() && b[i] < q.top().first)//一定要判堆是否为空
    		{
                int t = q.top().second; q.pop();//去掉不优的堆顶
                rest += b[t]; rest -= b[i];
                vis[t] = 0, vis[i] = 1;//对要买的商品打标急
                q.push(make_pair(b[i],i));
    		}
    	}
    	printf("%lld\n",ans);
    	for(int i = 1; i <= n; i++) if(vis[i]) printf("%d ",i);
    	return 0;
    }
    

    ENDING

  • 相关阅读:
    【转载】爸妈,求你们不要这么懂事
    【Selenium】各种方式在选择的时候应该怎么选择
    java动态绑定与静态绑定【转】
    java 字符串池【转】
    【转】java中PriorityQueue优先级队列使用方法
    【转】程序员的出路之一
    关于现在,关于未来
    计算机网络实验(router_sim)工具
    MIT算法导论课程
    最大间隙问题
  • 原文地址:https://www.cnblogs.com/genshy/p/13427940.html
Copyright © 2020-2023  润新知