PTA The Water Problem (10 점) (간격의 최상의 값을 찾기위한 선분 트리)

물 문제 (10 분)

물이없는 땅에서 물은 매우 제한된 자원입니다. 사람들은 항상 가장 큰 물 공급원을 위해 싸 웁니다. 수원의 크기를 나타내는 a1, a2, a3,…, an이있는 일련의 수원이 주어집니다. 각각 2 개의 정수 l과 r을 포함하는 일련의 쿼리가 주어지면 al과 ar 사이에서 가장 큰 수원을 찾으십시오.

입력 형식 :

먼저 테스트 케이스 수를 나타내는 정수 T (T ≤ 10)가 제공됩니다. 각 테스트 케이스에 대해 수원 수를 나타내는 선에 숫자 n (0 ≤ n ≤ 1000)이 있습니다. n 개의 정수가 각각 a1, a2, a3,…, an, 그리고 각 정수는 {1,…, 10 ^ 6}에 있습니다. 다음 줄에는 쿼리 수를 나타내는 숫자 q (0 ≤ q ≤ 1000)가 있습니다. 그 후, 가장 큰 수원을 찾아야하는 범위를 나타내는 두 개의 정수 l과 r (1 ≤ l ≤ r ≤ n)이있는 q 줄이 있습니다.

출력 형식:

각 쿼리에 대해 가장 큰 수원의 크기를 나타내는 정수를 출력합니다.

입력 샘플 :

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

샘플 출력 :

100
2
3
4
4
5
1
999999
999999
1

문제 해결

이 문제에 대한 직접적인 폭력적인 해결책도 가능합니다. 여기에서는 선분 트리를 사용하여 두 가지 방법으로 검색합니다.

암호

#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;
}

선분 트리 정보 : https://blog.csdn.net/qq_45349225/article/details/109338072
자세한 소개 : https://oi-wiki.org/ds/seg/

추천

출처blog.csdn.net/qq_45349225/article/details/109343385