I Hate It【線段樹 最值】

I Hate It
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 86070 Accepted Submission(s): 33036

Problem Description
很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。
這讓很多學生很反感。

不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績。

Input
本題目包含多組測試,請處理到文件結束。
在每個測試的第一行,有兩個正整數 N 和 M ( 0

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<iomanip>
using namespace std;
typedef int _____I;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
#define ERX(___I,__I,_I) for(_____I ___I = __I;___I <  _I; ___I++)
#define ERD(___I,__I,_I) for(_____I ___I = __I;___I <= _I; ___I++)
#define RED(___I,__I,_I) for(_____I ___I = __I;___I >= _I; ___I--)

const int maxnode =1<<19; //2的19 次方 
const int maxx =2e6+10;

struct act{
    int value;
    int left,right;
}node[maxnode];//所有的節點


int father[maxx];

void buildtree(int i,int left,int right){
    node[i].left=left;
    node[i].right=right;
    node[i].value= 0;
    if(left==right){ father[left]=i;return ;}

    buildtree(i<<1,left,(int)(floor(left+right)/2.0)); //向左進行循環 
    buildtree((i<<1)+1,(int)(floor(left+right)/2.0)+1,right);//向右進行循環 
}

void updatetree(int ri){ //更新區間的 最大值 
    if(ri==1) return ;
    int fi=ri/2; //臨時處理該節點下的 兩個兒子的 最大值 並賦值給 該點的 value 
    int a=node[fi<<1].value; //左兒子vaule  
    int b=node[(fi<<1)+1].value; // 右兒子的 value 
    node[fi].value=max(a,b);  //將兩個兒子的 value 賦值給 該節點的 最大值 
    updatetree(ri/2); //向上更新 
}
int Max;

void query(int i,int l,int r){ //查詢區間的最大值 
    if(node[i].left==l&&node[i].right==r){ //如果要查詢的區間就是 該區間 就進行更新最大值 
        Max=max(Max,node[i].value);  //將劃分的幾個區間 都進行一個 最大值的篩選 
        return ; //結束該層遞歸 
    }
    i=i<<1; //i的2次方 該節點的 左兒子 
    if(l<=node[i].right){ //左區間 在 當前節點的 右區間的左邊  說明右交集 
        if(r<=node[i].right) query(i,l,r); //繼續進行 遞歸 並且r在right的 左邊就進行 l r的遞歸求解 
        else query(i,l,node[i].right); //如果r大於該節點的右邊界 下一次遞歸就進行 l 到 最大的右區間的位置 
    }

    i++; //該節點的右兒子 
    if(r>=node[i].left){ //如果需要查詢的右區間 大於該點的右區間 
        if(l>=node[i].left) query(i,l,r);//並且需要查詢的左區間 大於該點的左區間 那麼久進行 l r的查詢 
        else query(i,node[i].left,r); //否則 就進行該區間的向下的遞歸 
    } 
}
int main(){
    int n,m,q;
    ios::sync_with_stdio(false);
    while(cin>>n>>m){
        buildtree(1,1,n);//建樹
        ERD(i,1,n){
            cin>>q;
            node[father[i]].value=q;
            updatetree(father[i]);
        }
        string op;
        int a,b;
        while(m--){
            cin>>op>>a>>b;
            if(op[0]=='Q'){
                Max=0;
                query(1,a,b);//查詢該區間的最大值
                cout<<Max<<endl;
            }
            else{
                node[father[a]].value=b;//該點的值等於 value
                updatetree(father[a]);//並進行更新 最大值  該函數的作用就是 將區間中的最大值 賦給每個區間 就是該區間的最大值 
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章