zoukankan      html  css  js  c++  java
  • 【2018杭电多校Round8 L】From ICPC to ACM

    题意

    一共有k个月
    第i个月原材料价格为c_i ,制造一台电脑要花费一个原材料和m_i元,最多能生产p_i台电脑,客户需求d_i台,
    当月卖出的原材料和电脑不收取存储费用,没用完的原材料和电脑可以留到下个月
    第i个月能存放e_i台电脑价格为E_i,存放原材料容量无限价格为R_i
    求满足每个月客户需求的最小成本

    分析

    1. 因为原材料存储容量无限,如果这个月的c_i加上R_i+1小于c_i+1,那么c_i+1 = c_i+R_i,以此可以得到每个月最便宜的原材料价格。
      进而,我们可以换成原材料不要钱,制造一台电脑的费用是c_i+m_i。
      进而,我们可以考虑,尽可能多的制造电脑(依据产能),然后卖出客户需求数量,再扔掉超出下个月仓库限制的数量,制造电脑不要钱,只有卖出的时候才算钱,如果扔掉就相当于没有制造过。
      所有制造出来的电脑每个月的成本都会加上一个E_i,所以考虑优先卖掉最便宜的电脑,扔掉最贵的电脑。
    2. 解决插入元素,删除最小的若干元素,最大的若干元素
      使用multiset,元素为一个二元组<价格,数量> ,每次删除头尾的若干元素就好
      到第i个月,当月存储成本是E_i,有些已经在仓库里的元素其实还加上了∑(k=begin→i-1)E_k,用前缀和思想,我们可以维护一个值add,表示第2个月到当前的所有的存储费用总和,那么插入元素的时候成本可以减去这个add,以后所有元素求费用的时候都加上add

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 5e4+5;
    const int inf = 0x3fffffff;
    multiset< pair<long long,int> >st;
    int c[N],d[N],m[N],p[N],e[N],R[N],E[N],n;
    long long ans,add,tot;
    int main(){
        int _;scanf("%d",&_);
        while(_--){
    	st.clear();ans=0LL,add=0,tot=0;;
    	scanf("%d",&n);
    	c[0] = inf;
    	for(int i=1;i<=n;i++) scanf("%d%d%d%d",&c[i],&d[i],&m[i],&p[i]);
    	for(int i=2;i<=n;i++) scanf("%d%d%d",&e[i],&R[i],&E[i]);
    	e[n+1] = 0;
    	int flag = 0;
    	for(int i=1;i<=n;i++){
    	    c[i] = c[i]<c[i-1]+R[i]?c[i]:c[i-1]+R[i];
    	    add+=E[i];
    	    st.insert(make_pair(c[i]+m[i]-add,p[i]));tot+=p[i];
    	    if(tot<d[i]){ flag = 1;break;}
    	    tot-=d[i];
    	    auto it = st.begin();
    	    while(d[i]>(it->second)){
    		d[i]-=(it->second);
    		ans+=it->second*1LL*(add+(it->first));
    		it = st.erase(it);
    	    }
    	    if(d[i]){
    		int x = it->first,y = it->second-d[i];
    	        ans+=d[i]*1LL*(add+x);
    		st.erase(it);
    		st.insert(make_pair(x,y));
    	    }
    	    if(tot>e[i+1]){
    		int dec = tot-e[i+1];
    		tot=e[i+1];
    		auto it = st.end();it--;
    		while(dec>it->second){
    		    dec-=it->second;
    		    it=st.erase(it);it--;
    		}
    		if(dec){
    		    int x = it->first,y = it->second-dec;
    		    st.erase(it);
    		    st.insert(make_pair(x,y));
    		}
    	    }
    	}
    	if(flag == 1){puts("-1");}
    	else {printf("%lld
    ",ans);}
        }
    }
    
    
  • 相关阅读:
    nyoj 19-擅长排列的小明(STL-next_permutation())
    航空概论(历年资料,引之百度文库,PS:未调格式,有点乱)
    2018年航空概论课后作业(PS:部分答案不正确, 综合得分:83.6)
    suseoj The wheat of the prime minister
    java后台校验 hibernate validator
    图片文件上传
    Servlet之javax.servlet包
    Maven置标签<scope>
    Windows下安装Redis
    MySQL函数GROUP_CONCAT() 实现多条数据合并
  • 原文地址:https://www.cnblogs.com/greenty1208/p/9485870.html
Copyright © 2011-2022 走看看