hduoj 1754 I Hate it

I Hate it

对于区间的值进行修改与查询最大,采用线段树解决。用一个变量来记录某个区间的最大值,同时每次更新后,需要递归回调每个区间的子区间的最大值。用于更新父节点的最大值。程序如下:

/*
ID: csuchenan
PROG: hduoj 1754 I hate it
LANG: C++
*/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define max(a , b) (a) > (b) ? (a) : (b)

#define MAXN 200005
#define MY_MAX -1



struct Node{
	
	int left  ;
	int right ;
	int nmax  ;
}node[MAXN * 4] ;

void build(int left , int right , int layer) ;
void query(int left , int right , int layer , int &nmax) ;
void update(int pos , int nval  , int layer) ;
void insert(int pos , int nval  , int layer) ;

int n ;
int m ;

void work() ;

int main(int argc , char * argv[]){

	while(scanf("%d %d" , &n , &m)!=EOF)
		work() ;
		
	return 0 ;
}

void work(){

	//build the tree
	build(1 , n , 1) ;
		
	int i ;
	int data ;
	
	i = 1 ;
	while(i <= n){
		
		scanf("%d" , &data)  ;
		
		//insert the data into the tree
		insert(i , data , 1) ;
		
		i++ ;
	}
	
	char c ;
	
	i = 0 ;
	
	int p ;
	int q ;
	int nmax  ;

	while(i < m){
		
		getchar() ;	
		
		scanf("%c %d %d" , &c , &p , &q) ;
			
		if(c == 'Q'){
		
			nmax = MY_MAX ;
			query(p , q , 1 , nmax) ;
			printf("%d\n" , nmax)   ;
		}
		else{
			update(p , q , 1) ;
		}
		
		i ++ ;
	}
}

void build(int left , int right , int layer ){
	
	node[layer].left = left ;
	node[layer].right = right ;
	node[layer].nmax = MY_MAX ;
	
	if(left == right){
		return  ;
	}
	
	int mid = (left + right) / 2 ;
	
	int llayer = layer * 2 ;
	int rlayer = layer * 2 + 1 ;
	
	build(left , mid , llayer) ;
	build(mid + 1 , right , rlayer) ;
	
	return ;
}

void insert(int pos , int nval , int layer){
	
	if(node[layer].nmax < nval){
	
		node[layer].nmax = nval ;
	}
	
	if(pos == node[layer].left && pos == node[layer].right){
		return ;
	}
	
	int mid = (node[layer].left + node[layer].right) / 2 ;
	
	int nlayer ;
	
	if(mid >= pos){
	
		nlayer = layer * 2 ;
		insert(pos , nval , nlayer) ;
		
		return ;
	}
	
	nlayer = layer * 2 + 1 ;
	insert(pos , nval , nlayer) ;
	
	return ;
}

void update(int pos , int nval , int layer){
	
	if(node[layer].left == pos && node[layer].right == pos){
		node[layer].nmax = nval ;
		return ;
	}
	
	int mid = (node[layer].left + node[layer].right) / 2 ;
	
	int llayer ;
	int rlayer ;
	
	llayer = layer * 2 ;
	rlayer = layer * 2 + 1 ;
	
	if(pos <= mid){
		
		update(pos , nval , llayer) ;
	}
	else{
		update(pos , nval , rlayer) ;
	}
	
	node[layer].nmax = max(node[llayer].nmax , node[rlayer].nmax) ;
	return ;
}

void query(int left , int right , int layer , int &nmax){

	if(node[layer].left == left && node[layer].right == right){
		
		nmax = max( node[layer].nmax , nmax );
		return ;
	}
	
	int mid = (node[layer].left + node[layer].right) / 2 ;
	int nlayer ;
	
	if(right <= mid){
		
		nlayer = layer * 2 ;
		query(left , right , nlayer , nmax ) ;
		return ;
	}
	
	if(left > mid){
		
		nlayer = layer * 2 + 1 ;
		query(left , right , nlayer , nmax) ;
		return ;
	}
	
	nlayer = layer * 2 ;
	
	query(left , mid , nlayer , nmax) ;
	query(mid + 1 , right , nlayer + 1 , nmax) ;
	
	return ;
	
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值