bzoj5088 wash
Posted zzqtxdy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj5088 wash相关的知识,希望对你有一定的参考价值。
题目大意
有(n)个洗衣机,每次只能洗一件衣服,分别需要(a_1,a_2,...a_n)分钟;(m)个烘干机,每次只能烘干一件衣服,分别需要(b_1,b_2,...b_m)分钟。要洗并烘干(l)件衣服,问最少需要的时间。
题解
考虑只用洗衣服,相当于一开始(x_i=1),每次选一个(i),(ans=max{ ans,x_i*a_i}),(++x_i)。
显然每次选最小的,否则交换后更优。用堆维护一下就行了。
这样我们可以预处理出每件衣服在什么时候洗好。
考虑一个烘干机,它需要的时间为(b),(c_1,c_2,...c_n)这些时间都有一件洗完的衣服送过来。
显然是送几件衣服马上烘干,让烘干机能工作就工作,这样第一件衣服时间为(c_1+b),第二件为(max{ c_1+2*b,c_2+b}),...,第(n)件为(max{c_1+n*b,c_2+(n-1)*b,...,c_{n-1}+2*b,c_n+b})
按时间从晚到早考虑就是每件衣服用一个烘干机,烘干机用第(x)次代价为(x*b),加上原有洗衣服的时间贡献到答案。
考虑多个烘干机,从晚到早考虑洗好的衣服,每次选一个烘干机。相当于一开始(x_i=1),每次选一个(i),(ans=max{ ans,a+x_i*b_i}),(++x_i)。
这里(a)是单调递减的,所以我们要求越小的越靠前,这样就可以像上面那样贪心了。
为什么这个贪心中不会出现“把前面一个扩大一点,后面一个缩小一点,使答案更平均”这种情况呢?我们换一种角度考虑,相当于有(b_1,2*b_1,...,l*b_1,b_2,2*b_2,...,l*b_2,...b_1,2*b_m,...,l*b_m)这(l*m)个数,选出最小的(l)个与(a)配对,那么我们选出的数都是固定的,最优情况会紧密挨在一起,就不会出现一个扩大一个缩小的情况了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> pll;
LL rd(){
LL x=0,flg=1;
char c=getchar();
for (;(c<48||c>57)&&c!='-';c=getchar());
if (c=='-') flg=-1,c=getchar();
for (;c>47&&c<58;x=x*10+c-48,c=getchar());
return flg*x;
}
const int mxn=1000010;
int n,m,k;
LL a[mxn],b[mxn];
priority_queue<pll> q;
int main()
{
n=rd(),k=rd(),m=rd();
for (int i=1,x;i<=k;++i)
x=rd(),q.push(make_pair(-x,x));
for (int i=1;i<=n;++i){
pll x=q.top();
q.pop();
a[i]=-x.first;
x.first-=x.second;
q.push(x);
}
for (;!q.empty();q.pop());
for (int i=1,x;i<=m;++i)
x=rd(),q.push(make_pair(-x,x));
LL ans=0;
for (int i=n;i;--i){
pll x=q.top();
q.pop();
ans=max(ans,a[i]-x.first);
x.first-=x.second;
q.push(x);
}
printf("%lld
",ans);
return 0;
}
以上是关于bzoj5088 wash的主要内容,如果未能解决你的问题,请参考以下文章
hdu 5088 Revenge of Nim II(BestCoder Round #16)