# 递增序列查询算法总结



## 题目描述



给定一个递增的正整数序列，针对不同的查询输出对应结果。查询类型包括查找最大下标、最小下标、数字范围计数、比某个数大的最小数字、比某个数小的最大数字等。



## 输入格式



1. 第一行：一个整数 `n`，代表序列的长度（下标从0开始到 `n-1`）。
2. 第二行：`n` 个整数，代表序列对应位置上的数。
3. 第三行：一个整数 `m`，代表查询次数。
4. 接下来的`m`行，每行是以下五种类型之一：
   - `0 x`：查询数字 `x` 出现的最大下标，若不存在则输出 -1。
   - `1 x`：查询数字 `x` 出现的最小下标，若不存在则输出 -1。
   - `2 x y`：查询大于等于 `x` 且小于等于 `y` 的数字的个数（保证 `x <= y`）。
   - `3 x`：查询比 `x` 大且下标最小的数字的大小，若不存在则输出 -1。
   - `4 x`：查询比 `x` 小且下标最大的数字的大小，若不存在则输出 -1。



## 输出格式



输出每个查询的结果，每个结果占一行。



## 算法思路



1. **初始化**：读取输入的序列和查询数。
2. **二分查找**：
   - **类型 0**：使用二分查找找到 `x` 的最大下标。
   - **类型 1**：使用二分查找找到 `x` 的最小下标。
   - **类型 2**：使用二分查找找到 `x` 和 `y` 的范围，计算范围内的元素个数。
   - **类型 3**：使用二分查找找到第一个比 `x` 大的元素。
   - **类型 4**：使用二分查找找到最后一个比 `x` 小的元素。
3. **输出结果**：将所有查询结果依次输出。



## 示例代码



```c
c#include <stdio.h>

int findMaxIndex(int a[], int n, int x) {
    int l = 0, r = n - 1, res = -1;
    while (l <= r) {
        int m = l + (r - l) / 2;
        if (a[m] == x) {
            res = m; 
            l = m + 1; 
        } else if (a[m] < x) {
            l = m + 1; 
        } else {
            r = m - 1; 
        }
    }
    return res;
}

int findMinIndex(int a[], int n, int x) {
    int l = 0, r = n - 1, res = -1;
    while (l <= r) {
        int m = l + (r - l) / 2;
        if (a[m] == x) {
            res = m; 
            r = m - 1; 
        } else if (a[m] < x) {
            l = m + 1; 
        } else {
            r = m - 1; 
        }
    }
    return res;
}

int countInRange(int a[], int n, int x, int y) {
    int leftIndex = findMinIndex(a, n, x);
    int rightIndex = findMaxIndex(a, n, y);
    if (leftIndex == -1 || rightIndex == -1) return 0;
    return rightIndex - leftIndex + 1;
}

int findFirstGreater(int a[], int n, int x) {
    int l = 0, r = n - 1, res = -1;
    while (l <= r) {
        int m = l + (r - l) / 2;
        if (a[m] > x) {
            res = a[m]; 
            r = m - 1; 
        } else {
            l = m + 1; 
        }
    }
    return res;
}

int findLastSmaller(int a[], int n, int x) {
    int l = 0, r = n - 1, res = -1;
    while (l <= r) {
        int m = l + (r - l) / 2;
        if (a[m] < x) {
            res = a[m]; 
            l = m + 1; 
        } else {
            r = m - 1; 
        }
    }
    return res;
}

int main() {
    int n, m;
    scanf("%d", &n);
    int a[n];

    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }

    scanf("%d", &m);
    for (int i = 0; i < m; i++) {
        int type, x, y;
        scanf("%d", &type);
        if (type == 0) {
            scanf("%d", &x);
            printf("%d\n", findMaxIndex(a, n, x));
        } else if (type == 1) {
            scanf("%d", &x);
            printf("%d\n", findMinIndex(a, n, x));
        } else if (type == 2) {
            scanf("%d %d", &x, &y);
            printf("%d\n", countInRange(a, n, x, y));
        } else if (type == 3) {
            scanf("%d", &x);
            printf("%d\n", findFirstGreater(a, n, x));
        } else if (type == 4) {
            scanf("%d", &x);
            printf("%d\n", findLastSmaller(a, n, x));
        }
    }

    return 0;
}
c
```



## 示例



### 输入



```
10
1 1 1 3 4 5 5 5 5 8
5
0 5
1 5
2 1 5
3 4
4 8
```



### 输出



```
8
5
9
5
5
```



## 总结



该算法使用二分查找处理多种查询类型，适合处理较大规模的输入数据，能够高效地返回查询结果。