基础贪心练习题

工厂有两条流水线 \(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\) 的结束时间,显然有如下形式:

\[\max\limits_{p=1}^{n} (\sum\limits_{i=1}^{p} a_i + \sum\limits_{i=p}^{n} b_i) \]

这是因为一定存在产品 \(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;
}
posted @ 2026-01-10 12:53  Oken喵~  阅读(22)  评论(0)    收藏  举报