• BZOJ.4946.[NOI2017]蔬菜(贪心 离线)


    题目链接

    因为有删除,考虑倒序处理某个p的询问。
    那么每天删除xi的蔬菜就变成了每天运来xi的蔬菜。那么我们取当前最优的即可,早取晚取都一样,不需要留给后面取,还能给后面更优的留出空间。
    这样就只需考虑现在了。于是我们能得到p为某个值的答案。多次询问显然需要递推。
    而p-1与p相比只是少卖了m的蔬菜。把收益最小的m个删掉即可。

    注意堆的插入删除顺序。
    复杂度(O(mqlogn))

    还有一种求询问p的方法,是直接按蔬菜价值排序,然后每次找到其出现位置往前覆盖。如果某天已卖m则用并查集合并掉。
    递推的时候sort一遍挨着删就可以。


    感觉离散化后线段树可做,第一次购买收益单独算一个,每个节点维护区间当前蔬菜种数、蔬菜总量、每天减少量。
    正序做,每一天就选m个最大的,然后减掉这m个。
    在某种蔬菜消失的那天直接Delete掉这种蔬菜(如果剩下1个下一天则Delete掉拆开的第一次购买收益)。
    这样复杂度还与m无关。
    不过...算了我就想想...写了写就弃了。


    //9424kb	1132ms
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    //#define gc() getchar()
    #define MAXIN 400000
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    #define mp std::make_pair
    #define pr std::pair<LL,int>
    #define MAX 100000
    typedef long long LL;
    const int N=1e5+3;
    
    int A[N],S[N],tot[N],dec[N],use[N];
    LL Ans[N];
    std::vector<int> v[N];
    std::queue<int> tmp;
    std::priority_queue<pr> q1;
    std::priority_queue<pr,std::vector<pr>,std::greater<pr> > q2;
    char IN[MAXIN],*SS=IN,*TT=IN;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    
    int main()
    {
    	int n=read(),m=read(),Q=read();
    	for(int i=1; i<=n; ++i)
    	{
    		A[i]=read(),S[i]=read(),tot[i]=read(),dec[i]=read();
    		if(!dec[i]) v[MAX].push_back(i);//上界!
    		else v[std::min(MAX,(tot[i]+dec[i]-1)/dec[i])].push_back(i);
    	}
    	LL ans=0;
    	for(int i=MAX; i; --i)
    	{
    		for(int j=0,k,l=v[i].size(); j<l; ++j)//处理第一次购买 
    			k=v[i][j], q1.push(mp(A[k]+S[k],k));
    		for(int l=m; l&&!q1.empty(); q1.pop())
    		{
    			int x=q1.top().second;
    			if(!use[x])
    				use[x]=1, ans+=q1.top().first, q1.push(mp(A[x],x)), --l;
    			else
    			{
    				int cnt=std::min(l,tot[x]-use[x]-(i-1)*dec[x]);
    				ans+=1ll*q1.top().first*cnt, l-=cnt;
    				if((use[x]+=cnt)!=tot[x]/*x=0可能会用完!*/) tmp.push(x);//delete
    			}
    		}
    		while(!tmp.empty()) q1.push(mp(A[tmp.front()],tmp.front())), tmp.pop();
    	}
    	Ans[MAX]=ans; int sum=0;
    	for(int i=1; i<=n; sum+=use[i++])
    		if(use[i]==1) q2.push(mp(A[i]+S[i],i));
    		else if(use[i]) q2.push(mp(A[i],i));
    	for(int i=MAX-1; i; --i)
    	{
    		Ans[i]=ans=Ans[i+1];
    		if(sum<=m*i) continue;//总数不够!
    		for(int l=sum-i*m/*同上!*/; l&&!q2.empty(); )
    		{
    			int x=q2.top().second;
    			if(use[x]==1) ans-=q2.top().first, --l, q2.pop();
    			else
    			{
    				int cnt=std::min(l,use[x]-1);
    				ans-=1ll*q2.top().first*cnt, l-=cnt;
    				if((use[x]-=cnt)==1) q2.pop(), q2.push(mp(A[x]+S[x],x));
    			}
    		}
    		sum=i*m, Ans[i]=ans;
    	}
    	while(Q--) printf("%lld
    ",Ans[read()]);
    
    	return 0;
    }
    
  • 相关阅读:
    破解版sublimeText3重新安装Package Control方法
    javascript中对象的属性的特性
    正则表达式元字符详解
    正则表达式学习笔记
    ExtJs布局大全
    js如何获取select下拉框的value以及文本内容
    ExtJS4之Ext.MessageBox的各种用法
    CODING 代码多仓库实践
    2019 DevOps 必备面试题——容器化和虚拟化
    拥抱微服务,CODING 即将上线单项目多仓库功能
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9669394.html
Copyright © 2020-2023  润新知