基础贪心练习题
工厂有两条流水线 \(A\) 和 \(B\),有 \(n\) 个产品需要在这两条流水线上加工。
第 \(i\) 个产品在流水线 \(A\) 上的加工时间为 \(a_i\),在流水线 \(B\) 上的加工时间为 \(b_i\)。
每个产品需要先在流水线 \(A\) 上加工,再在流水线 \(B\) 上加工。
一条流水线不能同时加工多个产品,求所有产品加工完成的最短时间。
\(A\) 流水线上的总加工时间是固定的,只要考虑 \(B\) 流水线即可。
不妨假设当前已经对所有产品排序,发现 \(B\) 的加工顺序应该与 \(A\) 的加工顺序相同。
即对于产品 \(x < y\),若先加工 \(a_x\) 再加工 \(a_y\),则应先加工 \(b_x\) 再加工 \(b_y\)。
此时我们考虑 \(b_n\) 的结束时间,显然有如下形式:
这是因为一定存在产品 \(p\),加工完 \(a_p\) 后立即加工 \(b_p\),产生贡献的是最大的 \(p\)。
接下来考虑进行邻项交换,不妨考虑相邻的产品 \(x < y\)。
我们记 \(s_A = \sum\limits_{i < x} a_i\),\(s_B = \sum\limits_{i > y} b_i\)。
-
先加工 \(x\) 再加工 \(y\)。
-
\(x\) 的贡献为 \(s_A + a_x + b_x + b_y + s_B\)。
-
\(y\) 的贡献为 \(s_A + a_x + a_y + b_y + s_B\)。
-
总的贡献为 \(s_A + s_B + a_x + b_y + \max(b_x,a_y)\)。
-
-
先加工 \(y\) 再加工 \(x\)。
-
\(y\) 的贡献为 \(s_A + a_y + b_y + b_x + s_B\)。
-
\(x\) 的贡献为 \(s_A + a_y + a_x + b_x + s_B\)。
-
总的贡献为 \(s_A + s_B + a_y + b_x + \max(b_y,a_x)\)。
-
我们希望 \(s_A + s_B + a_x + b_y + \max(b_x,a_y) < s_A + s_B + a_y + b_x + \max(b_y,a_x)\)。
两边同时减去 \(s_A + s_B + a_x + a_y + b_x + b_y\),得到 \(-\min(b_x,a_y) < -min(b_y,a_x)\)。
也就是说 \(\min(b_x,a_y) > \min(b_y,a_x)\),即 \(\min(a_x,b_y) < \min(a_y,b_x)\)。
然而直接把这个函数传到 sort 里是不对的,虽然其具有传递性,但其不具有可比性。
具体地,可能 \(x\) 与 \(y\) 无法比较,\(y\) 与 \(z\) 无法比较,但 \(x\) 和 \(z\) 可以比较。
考虑如何处理这种情况,我们不妨采用构造的方法,找到一种可能的排序方案。
具体地,考虑对于 \(x\),\(y\) 和 \(z\),满足 \(a_x < b_x\),\(a_y = b_y\) 且 \(a_z > b_z\)。
显然这样的排序方案符合要求,由此我们得到了以下三类情况:
-
\(a_i < b_i\),显然按照 \(a_i\) 从小到达排序。
-
\(a_i = b_i\),任意排序。
-
\(a_i > b_i\),按照 \(b_i\) 从大到小排序。
这样就结束了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Node{
long long a,b;
int op;
}node[25010];
bool operator <(const Node &lhs,const Node &rhs){
if(lhs.op!=rhs.op){
return lhs.op<rhs.op;
}
else if(lhs.op<=0){
return lhs.a<rhs.a;
}
else{
return lhs.b>rhs.b;
}
}
long long suma[25010],sumb[25010];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld %lld",&node[i].a,&node[i].b);
if(node[i].a<node[i].b){
node[i].op=-1;
}
if(node[i].a==node[i].b){
node[i].op=0;
}
if(node[i].a>node[i].b){
node[i].op=1;
}
}
sort(node+1,node+n+1);
for(int i=1;i<=n;i++){
suma[i]=suma[i-1]+node[i].a;
}
for(int i=n;i>=1;i--){
sumb[i]=sumb[i+1]+node[i].b;
}
long long ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,suma[i]+sumb[i]);
}
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号