1. 程式人生 > >I Hate It【線段樹 最值】

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; }