• 【CF436E】Cardboard Box(贪心)


    点此看题面

    • (n)个关卡,每个关卡你可以不进行任何操作,或花费(a_i)的代价获得一颗星,或花费(b_i)的代价获得两颗星。
    • 求获得至少(w)颗星的最小代价,并构造一种方案。
    • (nle3 imes10^5)(forall i,a_i<b_i)

    贪心+舍弃操作

    暂且不考虑恰好获得(w)颗星,而是仅考虑以最优策略去贪心,由于一次最多获得两颗星,因此最终也最多比(w)多出一颗星,只要略作调整即可。

    接下来的问题就是什么是我们的最优策略:

    • 如果(2a_ile b_i),那么可以把这个关卡拆成两个一星关卡,分别需要(a_i,b_i-a_i)的代价。
    • 如果(2a_i>b_i),那么最优策略肯定是将两星绑定一起选择。

    于是只要按代价排个序,直接贪心选择即可。

    如果恰好能选到(w)颗星就直接结束了,否则我们实际上可以舍弃一颗星,无非以下几种可能:

    • 不进行最后一次选择,去一个未操作过的关卡获得一颗星(代价(a_i)),或去一个获得过一颗星的关卡获得第二颗星(代价(b_i-a_i))。
    • 进行最后一次选择(假设代价为(xx)),去一个获得过一颗星的关卡放弃这颗星(代价(xx-a_i)),或去一个获得过两颗星的关卡放弃第二颗星(代价为(xx-(b_i-a_i)))。

    由于这个舍弃操作只需执行一次,直接暴力枚举过所有关卡即可。

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 300000
    #define LL long long
    using namespace std;
    int n,w,a[N+5],b[N+5],c[N+5];
    struct Data
    {
    	int p,x,c;I Data(CI i=0,CI a=0,CI b=0):p(i),x(a),c(b){}
    	I bool operator < (Con Data& o) Con {return x*o.c<o.x*c;}
    }s[2*N+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	char oc,FI[FS],*FA=FI,*FB=FI;
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    }using namespace FastIO;
    int main()
    {
    	RI i,t=0;for(read(n,w),i=1;i<=n;++i) read(a[i],b[i]),
    		2*a[i]<=b[i]?(s[++t]=Data(i,a[i],1),s[++t]=Data(i,b[i]-a[i],1)):s[++t]=Data(i,b[i],2);//根据2*a[i]和b[i]的关系拆分关卡
    	RI g=0;LL ans=0;for(sort(s+1,s+t+1),i=1;i<=t;++i) if((g+=s[i].c)>=w) break;else c[s[i].p]+=s[i].c,ans+=s[i].x;//贪心选择
    	RI tp=s[i].p,tx=a[s[i].p],pp=s[i].p,xx=s[i].x;if(g==w) {c[pp]+=s[i].c,ans+=xx;goto End;}//如果恰好w无需犹豫
    	#define F5(p,x) (tx>x&&(tp=p,tx=x))
    	for(i=1;i<=n;++i) !c[i]&&F5(i,a[i]),c[i]==1&&(F5(i,b[i]-a[i]),F5(-i,xx-a[i])),c[i]==2&&F5(-i,xx-(b[i]-a[i]));//枚举关卡获得一颗星,或获得两颗星后舍弃一颗星
    	if(tp>0) {++c[tp],ans+=tx;goto End;}c[pp]+=2,--c[-tp],ans+=tx;//更新最优解的方案
    	End:for(printf("%lld
    ",ans),i=1;i<=n;++i) putchar(48|c[i]);return 0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Delphi开发动态连接库的方法和规范
    EntityFramework+DomainDataSource+Silverlight完成数据读取分页排序与修改
    啊啊啊啊
    HTML、CSS、JavaScript从零开始系列文章
    从JAVA学思想,在.Net用……关于各种模型,备案以便查
    为ExtJS 4 系列树添加可将节点拖动到叶子节点上的功能,可配置
    在使用WCF RIA Services时所要注意的,不断更新中……
    修复EXTJS 4.0.2a在ie9与FIREFOX下字体过小、表格头部字体在Chrome下模糊的CSS补丁
    修复EXTJS 4.0.2a下面gridFilter的type为list时,不能从服务器读取列表数据的bug
    大学生程序员,"我们将要何去何从?!"
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF436E.html
Copyright © 2020-2023  润新知