此类算法题思路参考来自:博客
但是查找截断位置二分好像很复杂的样子,不太好写。这里我用倍增的思想代替上面的二分。
每次尝试走2^i 次方,类似于求LCA的方法。
找到截断位置后,再分别两个地方进行二分查找
并且用C语言实现
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],n;
int f[30];
int main()
{
f[0]=1;
for(int i=1;i<=20;++i) f[i]=f[i-1]*2;
scanf("%d",&n);
for(int i = 1;i <= n; ++i) scanf("%d",&a[i]);
int now=1;
for(int i = 20; i >= 0; --i){
if(now + f[i] > n) continue;
if(a[now + f[i]] >= a[now]) now = now + f[i];
}
int ans;
if(now == n) ans = 1;
else ans = now + 1;
printf("ans:%d\n",ans);//截断处
int m;scanf("%d",&m);//查询个数
while(m--)
{
int x;
scanf("%d",&x);
int l = ans,r = n;
int flag = 0;
if(a[l] <= x && x <= a[r]){
int res = -1;
while(l <= r)
{
int mid = l + r >> 1;
if(a[mid] >= x){
res = mid;
r = mid - 1;
}
else l = mid + 1;
}
if(res != -1){
if(a[res] == x) flag=1;
}
}
l = 1,r = ans - 1;
if(a[l] <= x && x <= a[r]){
int res = -1;
while(l <= r)
{
int mid = l + r >> 1;
if(a[mid] >= x){
res = mid;
r = mid - 1;
}
else l = mid + 1;
}
if(res != -1){
if(a[res] == x) flag=1;
}
}
if(flag){
puts("Yes");
}
else puts("No");
}
}
/*
8
12 20 34 77 1 4 7 10
100
10
6 8 9 10 1 2 3 4 5 6
*/