正解:贪心
解题报告:
传送门$QwQ$
$umm$直接看可能比较难想,可以先考虑另一个题?
有$n$个小怪,每打一只小怪会扣$a_i$的血,打完之后会回升$b_i$的血,问至少要多少血量才能使全程血量大于等于零?
$umm$这是个入门贪心题趴?就先把所有$b_i-a_i>0$的拿出来,然后按照$a_i$从小到大排序.然后对于$b_i-a_i<0$的,可以先反序看,就当作是从结尾走到那个转折点,就变成先扣$b_i$的血再回升$a_i$的血,所以就按$b_i$从小到大排序(反序从小到大,正序是从大到小嗷$QwQ$.然后答案就过程中扣得最多的那个节点的扣血量嘛$QwQ$
好然后再来看这题$QwQ$
发现其实这题和上一题的模型挺像的.
先考虑怎么求答案趴?发现答案就$\sum b$+浪费时间.所以现在就是要最小化浪费时间
浪费时间是什么呢?其实就类似于上一题那样儿的,每个任务会耗费$a_i$的时间,完成之后可以减少$b_i$的浪费,然后现在问浪费时间最少是多少?如果再上一题一点也可以说是,至少要预设多少浪费时间才能使全程不用浪费更多的时间?
所以就和上题一样地做就成,$over$
#includeusing namespace std; #define il inline #define gc getchar() #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) #define lb(x) lower_bound(st+1,st+st_cnt+1,x)-st const int N=1000+10; int n,gd_cnt,gs_cnt,ret,as,a[N],b[N]; struct node{int a,b,id;}gd[N],gs[N]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } il bool cmp(node x,node y){return x.a<y.a;} il bool cmq(node x,node y){return x.b>y.b;} int main() { //freopen("1248.in","r",stdin);freopen("1248.out","w",stdout); n=read();rp(i,1,n)a[i]=read();rp(i,1,n)b[i]=read(); rp(i,1,n){if(a[i]else gs[++gs_cnt]=(node){a[i],b[i],i};} sort(gd+1,gd+1+gd_cnt,cmp);sort(gs+1,gs+1+gs_cnt,cmq); rp(i,1,gd_cnt){ret-=gd[i].a;if(-ret>as)as=-ret;ret+=gd[i].b;} rp(i,1,gs_cnt){ret-=gs[i].a;if(-ret>as)as=-ret;ret+=gs[i].b;} rp(i,1,gd_cnt)as+=gd[i].b;rp(i,1,gs_cnt)as+=gs[i].b;printf("%d\n",as); rp(i,1,gd_cnt)printf("%d ",gd[i].id);rp(i,1,gs_cnt)printf("%d ",gs[i].id); return 0; }