哈理工oj(acm.hrbust.edu.cn) 1189【线段树】

 

区间最大值 II
Time Limit: 1000 MS Memory Limit: 65535 K
Total Submit: 182(39 users) Total Accepted: 66(28 users) Special Judge: No
Description

给一个有n个整数的序列a1, a2, a3, ..., an,然后有q个提问,每个提问为两个整数i、j,(i<=j),请你回答,在ai到aj中,最大值是多少。

注意:1 <= n,q <= 100000, ai在int整型表示的范围内。

Input
有多组测试数据。
每组测试数据的第一行为一个整数n,表示有n个数;
第二行为n个整数,表示a1,a2,..an;
第三行为q,表示q个提问。
接下来有q行,每行两个数i, j, (i <= j)。
Output
每组测试数据先输出一行"Case n:", n从1开始计数;

接下来有q行,每行对应一个提问,每行只有一个整数,为ai到aj间的最大值。

 

Sample Input
3
1 3 2
2
1 2
2 3
4
1 2 3 4
3
1 2
2 4
1 1
Sample Output
Case 1:
3
3
Case 2:
2
4
1
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>

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

struct node {
	int lvalue, rvalue; //左右边界的值。
	int v; //这个节点中的最大值。
	struct node *pl, *pr; //左右孩子的指针。
};

//构建一个左右边界从a到b的线段树,返回指向跟节点的指针。
struct node *buildtree(int a, int b)
{
	struct node *p = (struct node*)malloc(sizeof(struct node));
	p->lvalue = a;
	p->rvalue = b;
	p->v = INT_MIN; //节点中最大值初始化为最小的整数。
	if(a == b) return p;

	p->pl = buildtree(a, (a+b)/2);
	p->pr = buildtree((a+b)/2 + 1, b);
	return p;
}

//插入函数。参数:指向节点的指针p,要插入的位置pos,要插入的值val。
void insert(struct node *p, int pos, int val)
{
	//找到了位置,插入val.
	if(p->lvalue == p->rvalue) {
		p->v = val;
		return ;
	}
	//如果要插入值的位置pos在该节点的左子树上,则插入左子树上。
	//否则插入到右子树上。
	if(pos <= (p->lvalue + p->rvalue)/2) {
		insert(p->pl, pos, val);
	} else {
		insert(p->pr, pos, val);
	}
	//该节点的最大值为该节点左子树和右子树的最大值。
	p->v = max(p->pl->v, p->pr->v);
}

//查找函数,在区间a和b中查找最大的值。
int search(struct node *p, int a, int b)
{
	int ans = INT_MIN;
	//不太好理解啊,画画图吧,可以帮助理解。
	if(a <= p->lvalue && b >= p->rvalue) {
		return p->v;
	}
	if(a <= (p->lvalue + p->rvalue)/2) {
		int tmp = search(p->pl, a, b);
		if( tmp > ans ) ans = tmp;
	}
	if(b > (p->lvalue + p->rvalue)/2) {
		int tmp = search(p->pr, a, b);
		if( tmp > ans ) ans = tmp;
	}
	return ans;
}

//释放内存。
void free_memory(struct node *p)
{
	if(p->lvalue == p->rvalue) return;
	free_memory(p->pl);
	free_memory(p->pr);
	free( p );
}

int main()
{
	int n, t = 0;
	while(scanf("%d", &n) != EOF) {
		int i, q;
		printf("Case %d:\n", ++t);
		struct node *root = buildtree(1, n);
		for(i = 1; i <= n; i++) {
			int v;
			scanf("%d", &v);
			insert(root, i, v);
		}	
		scanf("%d", &q);
		for(i = 0; i < q; i++) {
			int a, b;
			scanf("%d %d", &a, &b);
			printf("%d\n", search(root, a, b));
		}
		free_memory( root );
	}
	return 0;
}

  

posted @ 2012-10-28 21:15  小猴子、  阅读(1425)  评论(0编辑  收藏  举报