题解:
一、 核心抽象:定义绝对坐标
为了衡量所有机器人同时工作的时长,我们必须在一个统一的时刻表(从 $t=0$ 开始)上观察它们。
-
系统启动时刻 ($S$):
只有当最后一个机器人充电完成,所有人才算全部进入工作状态。
因此,区间起点固定为:$S = \sum_{i=1}^{n} a_i$。 -
绝对离场时刻 ($E_i$):
第 $i$ 个充电的机器人,在完成前面所有充电任务后开始工作,它的“生命终点”在时间轴上的绝对位置是:
$$E_i = (\sum_{j=1}^{i} a_{p_j}) + b_{p_i}$$
- 目标函数:
全员共存的终点取决于最早离场的那个机器人。我们要最大化这个终点,即:
$$\max \left( \min_{i=1}^{n} { E_i } \right)$$
二、 逻辑猜想:固有生命力与排队策略
每个机器人都有一个固有绝对离场时刻(即它排在首位时的离场时间):$a_i + b_i$。
- 猜想:我们应该按照 $a_i + b_i$ 从大到小(降序) 进行充电。
- 直觉理由:
- $a_i + b_i$ 越大,代表这个机器人的“绝对续航”越强,它**“经得起等”**。即便它先下水,在后面的人充电时,它也能靠着极长的生命力撑到全员集合。
- 反之,那些 $a_i + b_i$ 很小的机器人,它们**“不耐等待”**。必须把它们放在序列的末尾,让它们刚充完电(此时时间已经接近 $S$)就立刻进入工作,直接参与共存。
三、 严谨证明:相邻交换法 (Exchange Argument)
考虑序列中相邻的两个机器人 $i$ 和 $j$。设它们之前的充电总时间为 $P$。
-
方案 1:$i$ 前 $j$ 后
它们的离场时刻分别是 $E_i = P + a_i + b_i$ 和 $E_j = P + a_i + a_j + b_j$。
局部最小值 $M_1 = \min(P + a_i + b_i, \ P + a_i + a_j + b_j)$。 -
方案 2:$j$ 前 $i$ 后
它们的离场时刻分别是 $E_j' = P + a_j + b_j$ 和 $E_i' = P + a_j + a_i + b_i$。
局部最小值 $M_2 = \min(P + a_j + b_j, \ P + a_j + a_i + b_i)$。
已知 $a_i + b_i > a_j + b_j$:
- 比较 $M_1$ 的两项与 $M_2$ 的第一项 $P+a_j+b_j$:
- 因为 $a_i + b_i > a_j + b_j$,所以 $P + a_i + b_i > P + a_j + b_j$。
- 因为 $a_i > 0$,所以 $P + a_i + a_j + b_j > P + a_j + b_j$。
- 由此可见,$M_1$ 的两项都严格大于 $P + a_j + b_j$。而 $M_2$ 的值受限于其第一项,最大只能等于 $P + a_j + b_j$。
- 结论:$M_1 > M_2$,即 $a+b$ 大的排在前面一定更优。
四、 代码实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+7;
int n,s,c,m=4e18,a[N],b[N],p[N];
bool cmp(int i,int j){return a[i]+b[i]>a[j]+b[j];}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
if(!(cin>>n))return 0;
for(int i=1;i<=n;++i){cin>>a[i]; s+=a[i];}
for(int i=1;i<=n;++i) cin>>b[i];
for(int i=1;i<=n;++i) p[i]=i;
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;++i){
int u=p[i];
c+=a[u];
m=min(m,c+b[u]);
}
cout<<max(0LL,m-s)<<endl;
return 0;
}