POJ3264:Balanced Lineup

http://poj.org/problem?id=3264

初次使用线段树解题,题目意思很清楚,查询区间[p ,q]中的最小数与最大数,然后输出二者之差。采用线段树解决,问题要简单的多,建线段树,然后插入,查询即可。在设计节点的时候根据题意除了要包含基本的元素外,还要包含该段元素中最小的,最大的。

程序如下:

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std ;
#define MY_MIN 99999999
#define MY_MAX -99999999

struct Node
{
	int left  ;
	int right ;
	int nMin  ;
	int nMax  ;
}node[600000] ;

void build(int left , int right , int step)  ;
void insert(int left , int right , int step) ;
void query(int left , int right , int step)  ;

int n ;
int m ;
int nMin ;
int nMax ;

int  main()
{
	int i ;
	int j ;
	int p ;
	int q ;
	
	scanf("%d %d" , &n , &m) ;
	
	build(1 , n , 0) ;
	
	i = 1 ;
	
	while(i <= n)
	{
		scanf("%d" , &p) ;
		insert(i , p , 0) ;
		i ++ ;
	}
	
	while(m--)
	{
		scanf("%d %d" , &p , &q) ;
	
		nMin = MY_MIN ;
		nMax = MY_MAX ;
		
		query(p , q , 0) ;
		
		printf("%d\n" , nMax - nMin) ;
	}
	return 0 ;
}

void build(int left , int right , int step)
{
	node[step].left = left ;
	node[step].right = right ;
	
	node[step].nMin = MY_MIN ;
	node[step].nMax = MY_MAX ;
	
	int pl = step * 2 + 1 ;
	int pr = step * 2 + 2 ;
	
	if(left != right)
	{
		int mid = (left + right)/2 ;
		
		build(left , mid , pl) ;
		build(mid + 1 , right , pr) ;
	}
}

void insert(int left , int right , int step)
{
	if(node[step].left == left && node[step].right == left)
	{
		node[step].nMin = node[step].nMax = right ;
		return  ;
	}
	
	//node[step].nMin = node[step].nMin > right ? right : node[step].nMin ;
	//node[step].nMax = node[step].nMax > right ? node[step].nMax : right ;
	
	node[step].nMin = min(right , node[step].nMin ) ;
	node[step].nMax = max(right , node[step].nMax ) ;
	
	int mid = (node[step].left + node[step].right)/2 ;
	int pl = step * 2 + 1 ;
	int pr = step * 2 + 2 ;
	
	if(mid < left)
		insert(left , right , pr) ;
	else if(mid >= left)
		insert(left , right , pl) ;		
}

void query(int left , int right , int step) 
{
	if(node[step].nMin >= nMin && node[step].nMax <= nMax)
		return ;
	
	if(node[step].left == left && node[step].right == right )
	{
		nMin = min(node[step].nMin , nMin) ;
		nMax = max(node[step].nMax , nMax) ;
		return ;
	}
	int mid = (node[step].left  + node[step].right) / 2 ;
	
	int pl = step * 2 + 1 ;
	int pr = step * 2 + 2 ;
	
	if(mid < left)
		query(left , right , pr) ;
	else if(mid >= right)
		query(left , right , pl) ;
	else
	{
		query(left , mid , pl) ;
		query(mid + 1 , right , pr) ;
	}		
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值