計蒜客:最甜的蘋果(線段樹)

Coder何發表於2024-10-29

樣例輸入

5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5

樣例輸出

5
6
5
9

這題我們需要維護的資訊,從區間的和變成了區間內的最大值。現在區間的內的某個值可能增大可能減小,若從上到下(從根到葉)進行節點更新,我們無法直接判斷目前區間內的最大的節點。

所以維護區間最大/最小值和維護區間和最大的不同就是:我們只能從下到上(從葉到根)進行節點更新。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 vector<int> maximum(200000 * 4);
 4 void modify(int p, int left, int right, int x, int y){
 5     if (left == right) {
 6         maximum[p] = y; //更新葉節點
 7         return;
 8     }
 9     int mid = (left + right) / 2;
10     if (x <= mid) {
11         modify(p * 2, left, mid, x, y);
12     } else {
13         modify(p * 2 + 1, mid + 1, right, x, y);
14     }
15     maximum[p] = max(maximum[p * 2], maximum[p * 2 + 1]); //葉節點更新完成後再更新最大值
16 }
17 int query(int p, int left, int right, int x, int y){
18     if (left >= x && right <= y){
19         return maximum[p];
20     }
21     int mid = (left + right) / 2, res, res1 = 0, res2 = 0;
22     if (x <= mid){
23         res1 = query(p * 2, left, mid, x, y);
24     }
25     if (y > mid){
26         res2 = query(p * 2 + 1, mid + 1, right, x, y);
27     }
28     return res = max(res1, res2);
29 }
30 int main(){
31     int n, m;
32     cin >> n >> m;
33     int temp, x, y;
34     char operation;
35     for (int i = 1; i <= n; ++i) {
36         cin >> temp;
37         modify(1, 1, n, i, temp);
38     }
39     while (m--) {
40         cin >> operation >> x >> y;
41         if (operation == 'Q') {
42             cout << query(1, 1, n, x, y) << endl;
43         } else {
44             modify(1, 1, n, x, y);
45         }
46     }
47 }