Hdu1754【线段树】

/*I Hate It 
Time Limit : 9000/3000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 0   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia 
Font Size: ← →
Problem Description
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。

不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。 
Input
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。

Output
对于每一次询问操作,在一行里面输出最高成绩。 
Sample Input
5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5

Sample Output
5
6
5
9

Hint
Huge input,the C function scanf() will work better than cin 
Author
linle 
Source
2007省赛集训队练习赛(6)_linle专场 
*/ 
#include<stdio.h>
int segtree[800001], n, m, data[200010], max;
int Max(int a, int b)
{
	return a>b?a:b;
}
void build_segtree(int l, int r, int rt)
{
	if(l == r)
	{ 
		scanf("%d", &segtree[rt] );//leaf num
		return ;
	}
	int k = (l + r)>>1; //save time
	build_segtree(l, k, rt<<1);
	build_segtree(k + 1,  r, rt<<1|1);
	segtree[rt] = Max(segtree[rt<<1], segtree[rt<<1|1]);//back
}
void update(int a, int b, int l, int r, int rt)
{
	if(l ==  r)
	{
		segtree[rt] = b;
		return ;
	}
	int k = (l+r)>>1;//save time
	if(a <= k)
	update(a, b, l, k, rt<<1);
	else 
	update(a, b, k + 1, r, rt<<1|1);
	segtree[rt] = Max(segtree[rt<<1], segtree[rt<<1|1]);//back
}
int question(int a, int b, int l , int r, int rt)
{
	if(a <= l && r <= b)//visit 
	{
		return segtree[rt];
	}
	int sum = 0, k = (l+r)>>1;
	if( a <= k)//the left part
	sum = Max(sum, question( a, b, l , k, rt<<1) );
	if(b > k )//the right part
	sum = Max(sum, question( a, b, k+1, r, rt<<1|1) );
	return sum;
}
int main()
{
	int i , j, a, b;
	char ch;
	while(scanf("%d%d", &n, &m) != EOF)
	{
		build_segtree( 1 , n , 1 );
		for(i = 0; i < m; ++i)
		{
			getchar();
			scanf("%c%d%d", &ch, &a, &b);
			if(ch == 'U')//update
			{
				update(a, b, 1, n, 1);//update the segtree 
			}
			else
			{
				printf("%d\n", question(a , b , 1, n, 1) );
			}
		}
	}
	return 0;
}



题意:标准的线段树,主要操作就是点更新和区间查询最大值。

思路:线段树模板。

注意:这里有个很坑的地方,Max不要用宏定义,用函数来做,不然会超时。。。(函数调用参数是计算好的,只计算一次;宏定义没有计算,运行时每次都要计算。)

你可能感兴趣的:(c)