1. 程式人生 > >I Hate It ——線段樹

I Hate It ——線段樹

Think:
1知識點:線段樹——區間最值+單點更新
2反思:注意陣列不要越界,開四倍即可

B - I Hate It 
很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。
這讓很多學生很反感。
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程式,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績。

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 Hint Huge input,the C function scanf() will work better than cin

以下為Accepted程式碼

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 2e5 + 4e2;

struct Node{
    int mav;
}node[N*4
]; void Build(int l, int r, int rt); void Updata(int rt); int find_mav(int L, int R, int l, int r, int rt); void up_v(int p, int v, int l, int r, int rt); int main(){ int n, m, L, R, p, v; char st[14]; while(~scanf("%d %d", &n, &m)){ Build(1, n, 1); while(m--){ scanf("%s", st); if(st[0] == 'Q'){ scanf("%d %d", &L, &R); printf("%d\n", find_mav(L, R, 1, n, 1)); } else if(st[0] == 'U'){ scanf("%d %d", &p, &v); up_v(p, v, 1, n, 1); } } } } void Build(int l, int r, int rt){ if(l == r){ scanf("%d", &node[rt].mav); return; } int mid = (l + r)/2; Build(l, mid, rt<<1); Build(mid+1, r, rt<<1|1); Updata(rt); } void Updata(int rt){ node[rt].mav = max(node[rt<<1].mav, node[rt<<1|1].mav); } int find_mav(int L, int R, int l, int r, int rt){ if(L <= l && r <= R) return node[rt].mav; int mid = (l + r)/2; int mav = -1; if(L <= mid) mav = max(mav, find_mav(L, R, l, mid, rt<<1)); if(R > mid) mav = max(mav, find_mav(L, R, mid+1, r, rt<<1|1)); return mav; } void up_v(int p, int v, int l, int r, int rt){ if(l == r){ node[rt].mav = v; return; } int mid = (l + r)/2; if(p <= mid && p >= l) up_v(p, v, l, mid, rt<<1); if(p > mid && p <= r) up_v(p, v, mid+1, r, rt<<1|1); Updata(rt); }