PTA El problema del agua (10 puntos) (árbol de segmento de línea para encontrar el mejor valor del intervalo)

El problema del agua (10 分)

En Land waterless, el agua es un recurso muy limitado. La gente siempre lucha por la mayor fuente de agua. Dada una secuencia de fuentes de agua con a1, a2, a3,…, una representa el tamaño de la fuente de agua. Dado un conjunto de consultas, cada una de las cuales contiene 2 números enteros lyr, averigüe cuál es la mayor fuente de agua entre al y ar.

Formato de entrada:

Primero se le da un número entero T (T ≤ 10) que indica el número de casos de prueba. Para cada caso de prueba, hay un número n (0 ≤ n ≤ 1000) en una línea que representa el número de fuentes de agua. Siguen n enteros, respectivamente a1, a2, a3,…, an, y cada entero está en {1,…, 10 ^ 6}. En la siguiente línea, hay un número q (0 ≤ q ≤ 1000) que representa el número de consultas. Después de eso, habrá q líneas con dos números enteros lyr (1 ≤ l ≤ r ≤ n) indicando el rango del cual debe encontrar la mayor fuente de agua.

Formato de salida:

Para cada consulta, genere un número entero que represente el tamaño de la fuente de agua más grande.

Muestra de entrada:

3
1
100
1
1 1
5
1 2 3 4 5
5
1 2
1 3
2 4
3 4
3 5
3
1 999999 1
4
1 1
1 2
2 3
3 3

Salida de muestra:

100
2
3
4
4
5
1
999999
999999
1

Resolución de problemas

También es posible una solución violenta directa a este problema, aquí usamos el árbol de segmento de línea para buscar de dos maneras.

Código

#include <algorithm>  //7-5 The Water Problem (10分)
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1e3 + 2;
int d[maxn * 4], num[maxn];

void build(int s, int t, int p) {
    
    
    if (s == t) {
    
      //对 [s, t] 区间建立线段树, 当前根的编号为 p
        d[p] = num[s];
        return;
    }
    int m = (s + t) >> 1;
    build(s, m, p * 2);          //最终可以求出d[p * 2]
    build(m + 1, t, p * 2 + 1);  //最终可以求出d[p * 2 + 1]
    d[p] = max(d[p * 2], d[p * 2 + 1]);
}

int getMaxValue(int l, int r, int s, int t, int p) {
    
    
    // 要查询区间 [l ,r] 的最大值
    if (l <= s && r >= t) return d[p];  //所求区间包含了已知区间
    int m = (s + t) / 2;                //二分查找
    if (r <= m) {
    
    
        return getMaxValue(l, r, s, m, p * 2);
    } else if (l > m) {
    
    
        return getMaxValue(l, r, m + 1, t, p * 2 + 1);
    } else {
    
    
        return max(getMaxValue(l, m, s, m, p * 2),
                   getMaxValue(m + 1, r, m + 1, t, p * 2 + 1));
    }
}

int main() {
    
    
    int T, n, q;
    cin >> T;
    while (T--) {
    
    
        // cin >> n;
        scanf("%d", &n);
        for (int j = 1; j <= n; j++) scanf("%d", &num[j]);
        build(1, n, 1);  //建立区间最值线段树

        cin >> q;
        int l, r;
        while (q--) {
    
    
            scanf("%d %d", &l, &r);
            cout << getMaxValue(l, r, 1, n, 1) << endl;  //二分查找
        }
    }

    system("pause");
    return 0;
}

Acerca del árbol de segmento de línea: https://blog.csdn.net/qq_45349225/article/details/109338072
Introducción detallada: https://oi-wiki.org/ds/seg/

Supongo que te gusta

Origin blog.csdn.net/qq_45349225/article/details/109343385
Recomendado
Clasificación