線分ツリー入門第一題!I Hate It HDU - 1754

2249 ワード

多くの学校では比較的な習慣が流行している.先生たちは聞くのが好きで、○○から○○までの中で、点数が一番高いのはいくらですか. 
これは多くの学生に反感を抱かせた. 
あなたが喜ぶかどうかにかかわらず、今あなたがしなければならないのは、先生の要求に従って、プログラムを書いて、先生の質問をシミュレートすることです.もちろん、先生はある同級生の成績を更新する必要があることがあります.
Inputこの問題には複数のテストが含まれています.ファイルが終わるまで処理してください. 
各試験の最初の行には、2つの正の整数NとM(0学生ID番号はそれぞれ1からNに編成される.
2行目はN個の整数を含み、このN個の学生の初期成績を表し、i番目の数はIDがiの学生の成績を表す. 
次はM行です.各行には1文字C('Q'または'U'のみ)と2つの正の整数A,Bがある. 
Cが「Q」である場合、IDがAからB(A,Bを含む)までの学生の中で、成績が最も高いかを尋ねる質問操作であることを示す. 
Cが「U」の場合、IDがAの学生の成績をBに変更する更新操作であることを示す. 
Outputは,問合せ操作ごとに1行に最高成績を出力する.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
        

分析:大部分の分析はコード注釈の上で、とても基礎的な入門問題です.
コード:
#include
#include
#include
using namespace std;
const int maxn = 200000+10;
const int NINF = 0xc0c0c0c0;
int n,m,k;
char action;
int grade[maxn*2],segtree[maxn*2];   //grade  ,segtree  , 。。
void build(int l,int r,int pos){
    if(r - l == 1){
        segtree[pos] = grade[l];
        return;
    } 
    int mid = (l+r)/2;
    build(l,mid,pos*2+1);
    build(mid,r,pos*2+2);
    segtree[pos] = max(segtree[pos*2+1],segtree[pos*2+2]);
}
void update(int id,int val){
    id += k-1;       // 
    segtree[id] = val;
    while(id > 0){
        id = (id-1)/2;
        segtree[id] = max(segtree[id*2+1],segtree[id*2+2]);
    }
}
int query(int ql,int qr,int l,int r,int pos){
    if(ql >= r || qr <= l) return NINF;
    if(ql <= l && qr >= r) return segtree[pos]; 
    int mid = (l+r)/2;
    return max(query(ql,qr,l,mid,pos*2+1), query(ql,qr,mid,r,pos*2+2));
}
int main()
{
    while(scanf("%d%d",&n,&m) != EOF){
        k = 1;
        while(k < n) k*=2;
        memset(grade,0xc0,sizeof(grade));      // , n , 。
                                                // segtree 。  。
        for(int i=0;i