标签:print 扩大 make return str 情况 一个 const namespace
有\(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\n",ans);
return 0;
}
标签:print 扩大 make return str 情况 一个 const namespace
原文地址:https://www.cnblogs.com/zzqtxdy/p/12181226.html