题目描述
对于一个长度为n的有序序列有以下两种操作:
1.对于给定的值x,找到大于等于x的值,如果有多个等于x的值那么就找到最后一个值为x的序列下标,否则就找到第一个大于x的序列下标
2.对于给定的值x,找到小于等于x的值,如果有多个等于x的值那么就找到最后一个值为x的序列下标,否则就找到第一个小于x的序列下标
如果找不到就输出"NO", 序列下标从1开始,序列保证有序。
输入格式
第一行包含两个正整数n(n <= 100000) 和 m(m <= 100000),分别表示序列大小和询问的次数。第二行是n个由空格隔开的有序序列a(其中0 <= ai <= 200000), 接下来m行每行一个整数x(0 <= x <= 200000)表示要查找的数。
输出格式
输出包含m行,m行包含两个整数x y, 分别代表第一个和第二个操作的答案,或者找不到就输出"NO"。
输入输出样例
输入 #1复制
5 5 1 3 3 3 5 1 2 3 5 6
输出 #1复制
1 1 2 1 4 4 5 5 NO 5
主要就是考察二分思想,关键在于细致,考虑好可能的情况
import java.io.*;
public class Main {//psvm:自动补main
public static void main(String[] args) throws IOException {
BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer r = new StreamTokenizer(re);
PrintWriter pr = new PrintWriter(new OutputStreamWriter(System.out));
r.nextToken();//缓冲,识别回车
int length = (int) r.nval;//序列长度
r.nextToken();
int askingcount = (int) r.nval;
int order[] = new int[length];
for (int i = 0; i < length; i++) {
r.nextToken();
order[i] = (int) r.nval;
}
int alltarger[] = new int[askingcount];
for (int i = 0; i < askingcount; i++) {
r.nextToken();
alltarger[i] = (int) r.nval;
}
if(length>0){
for (int i = 0; i < askingcount; i++) {
if (i != askingcount - 1) {
dichotomy(order, alltarger[i]);
System.out.println();
} else {
dichotomy(order, alltarger[i]);
}
}}
}
public static void dichotomy(int a[], int target) {//二分法查找
boolean flag = false;
int cursor = (a.length - 1) / 2;
int leftedge = 0;
int rightedge = a.length - 1;
int lasttimecursor = cursor;
if (target < a[0]) {
System.out.print(1 + " " + "NO");//若target小于所有值,则为1,No
} else if (a[0] <= target && target <= a[a.length - 1]) {//若在数组范围<=,>=
flag = true;
while (flag) {
if (a[cursor] < target) {
leftedge = cursor;
cursor = (leftedge + rightedge) / 2;
if (lasttimecursor == cursor) {
cursor = cursor;
break;
}
lasttimecursor = cursor;
} else if (a[cursor] > target) {
rightedge = cursor;
cursor = (leftedge + rightedge) / 2;
if (lasttimecursor == cursor) {
cursor = cursor - 1;
break;
}
lasttimecursor = cursor;
} else {
break;
}
}
int left = cursor;
int right = cursor;
if(a[cursor]!=target){//若不存在
System.out.print(left+2+" ");
left+=2;
}else{
for (int i = 0; i < a.length*2; i++) {//多个相同找最后,若无找
if (0 <= left && left < a.length) {
if (a[left] > target) {
System.out.print(left+" ");
break;
}
left++;
}else{
System.out.print(left+" ");
break;
}
}}
if(0<=left-1&&left-1<a.length&&a[left-1]==target){
System.out.print(left);
}else if(a[right]!=target){
System.out.print(right+1);
}
else{
for (int i = 0; i < a.length*2; i++) {
if (0 <= right && right < a.length) {
if (a[right] < target) {
System.out.print(right+1);
break;
}
right--;
}else{
System.out.print(right+1);
break;
}
}}
} else {
System.out.print("NO"+" "+a.length);
}
}
}