LG8481

题意

这题花了我好长时间才看明白。

一道二分查找题。每次查找一个数 \(t\)(保证一定能找到),每次 \(\operatorname{mid}\) 可以取 \(\left\lfloor\dfrac{(l+r)}{2}\right\rfloor\)\(\left\lfloor\dfrac{(l+r+1)}{2}\right\rfloor\),求最少需要多少次可以定位到 \(t\) 的位置。

分析

看到查询次数 \(q \le 100\),就立马想到了用搜索。

因为题目程序中 \(w\) 的取值有两种可能,即 \(0\)\(1\),所以可以分别令 \(w_1=0\)\(w_2=1\),分别将 \(w_1\)\(w2\) 代入题目程序中的 \(w\),并进行二分,递归下去即可。

由于最多定位次数不超过 $ \log_2 n$ 次,每一次有两种情况,所以时间复杂度即为 \(O(2^{\log_2 n} \times q)=O(nq)\),似乎有点危险,但洛谷评测机却跑得飞快。

代码如下:

#include <cstdio>
#include <iostream>
using namespace std;
int n,a[2000001],q,t,cnt;
template<typename ty=int>
inline ty read()
{
	ty n=0;char c=getchar();bool fl=0;
	while(c<33&&c!='-') c=getchar();
	if(c=='-') fl=1,c=getchar();
	while(c>='0'&&c<='9')
	{
		n=n*10+(c^48);
		c=getchar();
	}
	return fl?-n:n;
}
template<typename ty>
void pr(ty x)
{
	if(!x) return ;
	pr(x/10);
	putchar(x%10^48);
}
template<typename ty>
inline void write(ty x)
{
	if(x==0) putchar('0');
	else if(x<0) putchar('-'),x=-x;
	pr(x);
	putchar('\n');
}
void dfs(int l,int r,int x,int k)
{
	if(l==r)
	{
		cnt=min(cnt,k);
		return;
	}
	int m1=(l+r)/2,m2=(l+r+1)/2;
	if(a[m1]<x) dfs(m1+1,r,x,k+1);
	else dfs(l,m1,x,k+1);
	if(a[m2]-1<x) dfs(m2,r,x,k+1);
	else dfs(l,m2-1,x,k+1);
	return;
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	q=read();
	for(int i=1;i<=q;i++)
	{
		t=read();
		cnt=20;
		dfs(1,n,t,0);
		write(cnt);
	}
	return 0;
}
posted @ 2024-01-20 17:46  liyilang2021  阅读(3)  评论(0编辑  收藏  举报