I Hate It【線段樹 最值】
阿新 • • 發佈:2019-02-17
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;
}