I Hate It
阿新 • • 發佈:2021-11-11
原題連結:http://acm.hdu.edu.cn/showproblem.php?pid=1754
Problem Description:
很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。
這讓很多學生很反感。
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程式,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績。
Input:
本題目包含多組測試,請處理到檔案結束。
在每個測試的第一行,有兩個正整數 N 和 M ( 0<N<=200000,0<M<5000 ),分別代表學生的數目和操作的數目。
學生ID編號分別從1編到N。
第二行包含N個整數,代表這N個學生的初始成績,其中第i個數代表ID為i的學生的成績。
接下來有M行。每一行有一個字元 C (只取'Q'或'U') ,和兩個正整數A,B。
當C為'Q'的時候,表示這是一條詢問操作,它詢問ID從A到B(包括A,B)的學生當中,成績最高的是多少。
當C為'U'的時候,表示這是一條更新操作,要求把ID為A的學生的成績更改為B。
Output:
對於每一次詢問操作,在一行裡面輸出最高成績。
Sample Input:
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
Sample Output:
5
6
5
9
解題思路:
線段樹模板題,本題包含建樹、向上回溯、單點修改、區間查詢
AC程式碼:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int maxn = 200005; int g[maxn]; //定義成績陣列 int arr[maxn * 4]; //定義樹的資料陣列 void pushup(int node) { arr[node] = max(arr[node * 2], arr[node * 2 + 1]); //向上回溯 } void build(int l, int r, int node) { if (l == r) { arr[node] = g[l]; return; //判斷是葉子,賦值並退出函式 } int mid = (l + r) / 2; //取中值 build(l, mid, node * 2); //遞迴左子樹 build(mid + 1, r, node * 2 + 1); //遞迴右子樹 pushup(node); //回溯父代 } int query(int a, int b, int l, int r, int node) { if (a <= l && b >= r) return arr[node]; int maxm = 0; int mid = (l + r) / 2; if (a <= mid) maxm = max(maxm, query(a, b, l, mid, node * 2)); if (b > mid) maxm = max(maxm, query(a, b, mid + 1, r, node * 2 + 1)); return maxm; } void update(int a, int b, int l, int r, int node) //更新操作 { if (l == r) { arr[node] = b; return; } //判斷是葉子,把b賦給葉子 int mid = (l + r) / 2; if (a <= mid) update(a, b, l, mid, node * 2); else update(a, b, mid + 1, r, node * 2 + 1); pushup(node); } int main() { ios::sync_with_stdio(0); cin.tie(0); int N, M; //N為學生數,M為操作次數 while (cin>>N>>M) //輸入N,M { for (int i = 1; i <= N; i++) { cin>>g[i]; //輸入成績,從index為1開始 } build(1, N, 1); //建樹 char ch; //定義操作符 int a, b; //定義運算元 while (M--) { cin >> ch >> a >> b; if (ch == 'Q') cout<<query(a, b, 1, N, 1)<<endl; else update(a, b, 1, N, 1); } } return 0; }