目录
题目
B1. 严厉的老师(困难版)
每个测试用例时间限制:1.5 秒
每个测试用例内存限制:256 兆字节
纳雷克和措索瓦克忙着准备这一轮(活动),所以他们没来得及完成作业,于是决定抄袭大卫的作业。他们严厉的老师发现大卫没有作业,现在想惩罚他。她雇了其他老师来帮她抓住大卫。现在有 m 位老师一起在追他。幸运的是,教室很大,所以大卫有很多地方可以躲藏。
教室可以表示成一条一维直线,上面的格子从 1 到 n 编号(包含 1 和 n )。
一开始,所有 m 位老师和大卫都在不同的格子里。然后他们开始移动。在每一轮移动中:
大卫可以移动到相邻的格子,或者停留在当前格子。
然后,每位老师同时移动到相邻的格子,或者停留在当前格子。
这个过程会一直持续,直到大卫被抓住。当有任意一位老师(可能不止一位)和大卫处于同一个格子时,大卫就被抓住了。每个人都能看到其他人的移动,所以他们都会采取最优策略行动。
你的任务是找出在所有人都采取最优策略的情况下,老师们抓住大卫需要多少轮移动。
采取最优策略意味着学生以一种能让老师抓住他所需移动轮数最大化的方式移动;而老师们相互配合,以一种能让抓住学生所需移动轮数最小化的方式移动。
此外,由于纳雷克和措索瓦克认为这个任务很简单,他们决定针对大卫的位置给出 q 次询问。注意:这是简单版本,你只会得到一次询问。
输入
输入的第一行包含一个整数 t(1 ≤ t ≤ 10⁵),表示测试用例的数量。接下来是每个测试用例的描述。
每个测试用例的第一行包含三个整数 n、m 和 q(3 ≤ n ≤ 10⁹,m = 2,q = 1),分别表示直线上格子的数量、老师的数量和询问的数量。
每个测试用例的第二行包含 m 个不同的整数 b₁, b₂, …, bₘ(1 ≤ bᵢ ≤ n),表示老师们所在的格子编号。
每个测试用例的第三行包含 q 个整数 a₁, a₂, …, a_q(1 ≤ aᵢ ≤ n),表示每次询问时大卫所在的格子编号。
可以保证,对于任意的 i、j,满足 1 ≤ i ≤ m 且 1 ≤ j ≤ q 时,bᵢ ≠ aⱼ 。
输出
对于每个测试用例,输出 q 行,其中第 i 行包含第 i 次询问的答案。
说明
在第一个例子中,学生可以就待在 2 号格子。最初在 1 号格子的老师移动一步就能到达 2 号格子。因此,答案是 1。
在第二个例子中,学生应该就待在 1 号格子。最初在 3 号格子的老师移动两步就能到达 1 号格子。因此,答案是 2。
思路简述:
如果学生在所有老师左边,直接让学生去最左边,然后等着被抓
如果学生在所有老师右边,直接让学生去最右边,然后等着被抓
如果学生在老师中间,找到距离学生最近的两个老师,让学生去这两个老师的中间,然后等着被抓
总代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],q;
void solve()
{
int n,m,k;
cin >> n >> m >> k;
for(int i=1;i<=m;i++)
cin >> a[i];
sort(a+1,a+1+m);
int mn=a[1],mx=a[m];
while(k--)
{
int c;
cin >> c;
if(c<mn)//学生在所有老师左边
{
cout << mn-1<<endl;
}
else if(c>mx)//学生在所有老师右边
{
cout << n-mx<<endl;
}
else//学生被老师包夹,二分查找距离学生最近的两个老师的坐标
{
int l=1,r=m;
while(l+1!=r)
{
int mid=l+r>>1;
if(a[mid]>c)r=mid;
else l=mid;
}
cout << (a[r]-a[l])/2<<endl;
}
}
}
int main()
{
int q;
cin >> q;
while(q--)
{
solve();
}
}