Distinct

Distinct

题目

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>
#include<algorithm>
#include<iostream>
using namespace std;
struct note
{
	int a,b;
}a[100001];
int n,l,r;
bool pd(int mid)
{
	int now=a[1].b-mid+a[1].a;//第一队士兵尽可能向左移
	if (now-1>a[1].b+mid) return 0;//判断是否超过下一队
	for (int i=2;i<=n;i++)
	{
		now=max(now,a[i].b-mid)+a[i].a;//如果尽可能向左移,如果更上一对有交差就要从上一支队开始
		if (now-1>a[i].b+mid) return 0;//判断是否超过下一队
	}
	return 1;
}
bool cmp(note x,note y)//按坐标把士兵从小到大排序
{
	return x.b<y.b;
}
int main()
{
	scanf("%d",&n);//读入
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i].a);//读入
		r+=a[i].a;//求出要二分答案的最大值
	}
	for (int i=1;i<=n;i++) scanf("%d",&a[i].b);//读入
	sort(a+1,a+n+1,cmp);//按坐标把士兵从小到大排序
	while (l<=r)
	{
		int mid=(l+r)/2;//找出中间值
		if (pd(mid)) r=mid-1;//答案在左边
		else l=mid+1;//答案在右边
	}
	printf("%d",l);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值