1. 程式人生 > >線段樹 功能:update:單點替換 query:區間最值 hdu1754

線段樹 功能:update:單點替換 query:區間最值 hdu1754

hud 1754   http://acm.hdu.edu.cn/showproblem.php?pid=1754

(0)定義

#include <cstdio> 

#include <algorithm>

using namespace std;

const int maxn =222222;
int MAX[maxn<<2]; //  maxn *4;

(1) 建立線段樹

void PushUp(int rt) // rt :當前節點的編號

{                    //
更新該節點的資料 ,這裡是求該節點的最大值 MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]); // <<1==*2 ,<<1|1==*2+1; } void build(int l,int r,int rt)//建樹 ,[l.r]當前節點的區間,rt :當前的節點 { if(r==l){ //到達子葉節點, scanf("%d",&MAX[rt]); return ; } int m=(l+r)>>1; // 除以2
//左右遞迴 build(l,m,rt<<1); build(m+1,r,rt<<1|1); PushUp(rt); //更新資訊 }

(2)單點替換

void update(int p,int sc,int l,int r,int rt){
    //     P:替換第幾個,sc:更換的資料   在[l.r]中查詢 
         if(l==r){
             MAX[rt]=sc;
             return ;
         }
    int m=(l+r)>>1
; //判斷 p 左還是右 if(p<=m){ update(p,sc,l,m,rt<<1); }else{ update(p,sc,m+1,r,rt<<1|1); } PushUp(rt);// 子葉替換後 當前節點更新 }

(3) 區間最大值

int query(int L,int R,int l,int r,int rt){
        //[L,R] 所求區間  [l,r]當前區間 
    if(L<=l&&r<=R){
        return MAX[rt];
    }
    
    int m=(l+r)>>1;
    int ret=0;
    if(L<=m)ret=max(ret,query(L,R,l,m,rt<<1));
    if(m<R)ret=max(ret,query(L,R,m+1,r,rt<<1|1));
    return ret;    
} 

線段樹,不會的話可以多畫畫自己理解理解;

附上全部程式碼

#include<iostream>
#include <cstdio>  
#include <algorithm>
using namespace std;

const int maxn =222222;
int MAX[maxn<<2]; //  maxn *4;


void PushUp(int rt) //  rt :當前節點的編號 
{                    //更新該節點的資料 ,這裡是求該節點的最大值 
    MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);    //  <<1==*2 ,<<1|1==*2+1;
}
void build(int l,int r,int rt)//建樹 ,[l.r]當前節點的區間,rt :當前的節點 
{
    if(r==l){        //到達子葉節點,
        scanf("%d",&MAX[rt]);     
        return ; 
    } 
    int m=(l+r)>>1;  //  除以2
    //左右遞迴 
    build(l,m,rt<<1);     
    build(m+1,r,rt<<1|1); 
    
    PushUp(rt); //更新資訊 
}

//單點替換 
void update(int p,int sc,int l,int r,int rt){
    //     P:替換第幾個,sc:更換的資料   在[l.r]中查詢 
         if(l==r){
             MAX[rt]=sc;
             return ;
         }
    int m=(l+r)>>1;
    //判斷 p 左還是右 
    if(p<=m){
        update(p,sc,l,m,rt<<1);
    }else{
        update(p,sc,m+1,r,rt<<1|1);
    }
    PushUp(rt);// 子葉替換後 當前節點更新 
}

        //區間最大值 
int query(int L,int R,int l,int r,int rt){
        //[L,R] 所求區間  [l,r]當前區間 
    if(L<=l&&r<=R){
        return MAX[rt];
    }
    
    int m=(l+r)>>1;
    int ret=0;
    if(L<=m)ret=max(ret,query(L,R,l,m,rt<<1));
    if(m<R)ret=max(ret,query(L,R,m+1,r,rt<<1|1));
    return ret;    
} 
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        build(1,n,1);//  建樹 從 1 到 n ,當前節點為1 
         while(m--){
             char op[2];
             int a,b;
             scanf("%s%d%d",op,&a,&b);
             if(op[0]=='Q'){
                 int k=query(a,b,1,n,1);
                 printf("%d\n",k);
                 //cout<<k<<endl;
             }
             else
             update(a,b,1,n,1);
         } 
        
    }
    return 0;
}