题目描述
Daniel 正在玩一个战棋游戏。
现在 Daniel 有 n 队士兵站在 x 轴上。第 i 队士兵有 ai 人,坐标为 xi。
Daniel 看到一队士兵有这么多人,都站在同一个位置,他对此很不满意。他
想命令一些士兵移动到新的位置(必须是整点),使得不存在两个士兵站在同一个
位置。
为了节约时间,Daniel 希望每个士兵的移动距离的最大值尽可能小。请求出
这个最小值。
输入
第一行一个正整数 n,表示 Daniel 有多少队士兵。第二行 n 个正整数 ai,表示每队士兵的人数。第三行 n 个严格递增的 整数 xi,表示每队士兵的坐标。
输出
一行一个非负整数,表示每个士兵的移动距离的最大值的最小值
输入样例
2
2 3
0 2
输出样例
1
说明
样例解释
移动后,5 个士兵的坐标分别为 -1, 0, 1, 2, 3。
有 2 个士兵移动距离为 0,3 个士兵移动距离为 1,因此答案是1
思路
用二分,每一个士兵尽量靠左
#include<Algorithm>
#include<Iostream>
#include<Cstring>
#include<Cstdio>
#include<Cmath>
#define ll long long
using namespace std;
ll A[100250],F[100250];
ll n,m;
bool Check(ll K)
{
m=F[1]-K+A[1];//最少移动K步且靠最左
for(ll i=2;i<=n;++i)
{
if(m-1>F[i-1]+K)return 0;//判断是否超过K
m=max(m,F[i]-K)+A[i];//
}
if(m-1>F[n]+K)return 0;
else return 1;
}
int main()
{
// freopen("1.txt","r",stdin);
scanf("%lld",&n) ;
ll l=0,r=0;
for(ll i=1;i<=n;++i)
{
scanf("%lld",&A[i]);
l=max(A[i],l);
r+=A[i];
}
for(ll i=1;i<=n;++i)scanf("%lld",&F[i]);
l/=2;
while(l<=r)//二分
{
ll mid=(l+r)/2;
if(Check(mid))r=mid-1;
else l=mid+1;
}
printf("%lld",l);
return 0;
}