zoukankan      html  css  js  c++  java
  • P4480[BJWC2018]餐巾计划问题【三分,贪心】

    正题

    题目链接:https://www.luogu.com.cn/problem/P4480


    题目大意

    \(n\)天,第\(i\)天需要\(a_i\)个餐巾。

    每个餐巾价格为\(p\),使用完后有两种清洗方法

    1. 清洗\(m_1\)天,费用为\(c_1\)
    2. 清洗\(m_2\)天,费用为\(c_2\)

    求满足所有需求的最小花费

    \(1\leq n\leq 2\times 10^5,1\leq m_1,m_2\leq n,1\leq c_1,c_2,a_i\leq 100\)


    解题思路

    如果固定了购买的毛巾数量那么此题就有一个贪心的做法。

    首先先把购买的全部优先使用了

    然后如果快的那个洗法费用更低,那么显然全部用快的洗法。

    否则就是一个快但是贵,一个慢但是便宜。那么我们的决策就是能用慢的就不使用快的。这个可以用决策后延来解决,当我们需要毛巾的时候再决定前面的毛巾的洗法。

    这样的贪心是\(O(n)\)的,但是我们不能暴力枚举毛巾数量。

    感性理解的话不难费用根据毛巾的数量呈一个单谷状,所以我们可以直接三分出这个谷底即可。

    时间复杂度\(O(n\log (100n))\),因为\(deque\)比较慢所以我的标要开\(\text{-O2}\)才能过/kk


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=2e5+10,inf=2e9;
    int n,p,m1,m2,c1,c2,w[N];
    struct node{
    	int t,w;
    	node(int tt=0,int ww=0)
    	{t=tt;w=ww;return;}
    };
    deque<node> q1,q2,q3;
    int calc(int x){
    	int ans=x*p;
    	q1.clear();q2.clear();q3.clear();
    	for(int i=1;i<=n;i++){
    		while(!q1.empty()&&q1.front().t+m1<=i)
    			q2.push_back(q1.front()),q1.pop_front();
    		while(!q2.empty()&&q2.front().t+m2<=i)
    			q3.push_back(q2.front()),q2.pop_front();
    		int v=w[i],tmp=min(v,x);x-=tmp;v-=tmp;
    		while(v&&!q3.empty()){
    			tmp=min(v,q3.back().w);
    			v-=tmp;ans+=tmp*c2;
    			if(tmp==q3.back().w)q3.pop_back();
    			else q3.back().w-=tmp;
    		}
    		while(v&&!q2.empty()){
    			tmp=min(v,q2.back().w);
    			v-=tmp;ans+=tmp*c1;
    			if(tmp==q2.back().w)q2.pop_back();
    			else q2.back().w-=tmp;
    		}
    		if(v)return inf;
    		q1.push_back(node(i,w[i]));
    	}
    	return ans;
    }
    int main()
    {
    	scanf("%d%d%d%d%d%d",&n,&m1,&m2,&c1,&c2,&p);
    	if(m1>m2)swap(m1,m2),swap(c1,c2);
    	if(c1<c2)c2=c1,m2=m1;
    	for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    	int l=1,r=n*100;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(calc(mid)<calc(mid+1))r=mid-1;
    		else l=mid+1;
    	}
    	printf("%d\n",calc(l));
    	return 0;
    }
    
  • 相关阅读:
    ps切图保存所有切片为png
    指法练习 V1.0_haley(指法练习工具)
    zoj 4020 The 18th Zhejiang University Programming Contest Sponsored by TuSimple
    CF 某套题 O :Grid (简单BFS)
    codeforces 某套题s : surf(贪心 || 动态规划)
    STL模板整理 全排列
    STL模板整理 priority_queue
    STL模板整理 pair
    STL模板整理 set
    第八届省赛 B:Quadrat (打表找规律)
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14531279.html
Copyright © 2011-2022 走看看