hdu1754 區間更新查詢(單點更新+查詢求區間最大值)
阿新 • • 發佈:2018-11-30
I Hate It
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 106776 Accepted Submission(s): 40096
這讓很多學生很反感。
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程式,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績。
在每個測試的第一行,有兩個正整數 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。
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
#include<iostream> #include<algorithm> #include<vector> #include<math.h> #include<stdio.h> #include<string.h> #include<algorithm> const int n = 200050; using namespace std; int tre[n * 4]; void build(int num, int le, int ri)//建立線段樹 { if (le == ri)//如果區間左端點等於區間右端點,則輸入區間的每一個元素 { scanf("%d", &tre[num]); return; } int mid = (le + ri) / 2; build(num * 2, le, mid); build(num * 2 + 1, mid + 1, ri); tre[num] = max(tre[num * 2], tre[num * 2 + 1]);//通過子節點來初始化父親節點 } void update(int num, int le, int ri, int x, int y)//單點更新 { if (le == ri)//找到要更新的x節點所在位置,並對x節點值加y { tre[num] = y; return; } int mid = (le + ri) / 2; if (x <= mid) update(num * 2, le, mid, x, y); else update(num * 2 + 1, mid + 1, ri, x, y); tre[num] = max(tre[num * 2], tre[num * 2 + 1]); } int query(int num, int le, int ri, int x, int y)//區間查詢 { if (x <= le && y >= ri)//如果我們要查詢的[x,y]區間比[le,ri]大,那麼[le,ri]區間的值就是結果的一部分,直接返回 { return tre[num]; } int mid = (le + ri) / 2; int ans = 0;//ans是記錄查詢區間的最大值 if (x <= mid)//查詢左子樹 ans = max(ans, query(num * 2, le, mid, x, y)); if (y > mid)//查詢右子樹 ans = max(ans, query(num * 2 + 1, mid + 1, ri, x, y)); return ans; } int main() { int t, n; while (cin >> n >> t) { build(1, 1, n); char operate[10]; for (int i = 0; i < t; i++) { cin >> operate; int x, y; scanf("%d %d", &x, &y); if (operate[0] == 'U') { update(1, 1, n, x, y); } if (operate[0] == 'Q') { cout << query(1, 1, n, x, y) << endl; } } } return 0; }