【二分】Distinct

博客围绕战棋游戏中军队士兵移动问题展开。有n队士兵在x轴上,每队有一定人数,要使每个坐标只有一人,需让士兵移动。目标是求出每个士兵移动距离最大值的最小值。解题思路为先二分答案,再进行判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Distinct

题目大意:

有n个军队(有自己在x轴上的坐标),每个军队有一定的人,要一个坐标只有一个人,移动路程最大的士兵最少移动多长

原题:

题目描述

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<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,l,r,q,mid,a[100005],x[100005];
bool check(int dep)
{
	q=x[1]-dep+a[1];//尽量往左
	if (q-1>x[1]+dep) return false;//因为p是下一支队的开始,所以要-1
	for (int i=2;i<=n;++i)
	  {
	  	q=max(q,x[i]-dep)+a[i];//如果有交差就要从上一支队开始
	  	if (q-1>x[i]+dep) return false;//判断是否超过
	  }
	return true;
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;++i)
	  {
	  	scanf("%d",&a[i]);
	  	l=max(l,a[i]);//最小
		r+=a[i]; //最大
	  }
	for (int i=1;i<=n;++i)
	  scanf("%d",&x[i]);
	l/=2;
	while (l<=r)//二分
	  {
	  	mid=(l+r)/2;
	  	if (check(mid)) r=mid-1;
	  	else l=mid+1;
	  }
	printf("%d",l);
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值