hdu 1754 I Hate It (线段树功能:单点更新和区间最值)

转载请注明出处:http://blog.csdn.net/u012860063

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754


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


代码如下:

//线段树功能:update:单点替换 query:区间最值
//此题为Hdu 1754

#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
//lson和rson分辨表示结点的左儿子和右儿子
//rt表示当前子树的根(root),也就是当前所在的结点
const int maxn = 222222;
//maxn是题目给的最大区间,而节点数要开4倍,确切的来说节点数要开大于maxn的最小2x的两倍
int sum[maxn<<2];
int max(int x,int y)
{
	if(x > y)
		return x;
	return y;
}
void PushUP(int rt) //把当前结点的信息更新到父结点
{
	sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
}

void build(int l,int r,int rt)
{
	if (l == r)
	{
		scanf("%d",&sum[rt]);
		return ;
	}
	int mid = (l + r) >> 1;
	build(lson);
	build(rson);
	PushUP(rt);
}
void update(int p,int sc,int l,int r,int rt) 
{
	if (l == r) //叶节点
	{
		sum[rt] = sc;
		return ;
	}
	int mid = (l + r) >> 1;
	if (p <= mid)//递归更新左子树或者右子树
		update(p , sc , lson);
	else 
		update(p , sc , rson);
	PushUP(rt);
}
int query(int L,int R,int l,int r,int rt)
{//查询区间[L,R]中的最大值
	if (L <= l && r <= R)//当前结点完全包含在查询区间内
	{
		return sum[rt];
	}//要取rt子节点的值时,也要先把rt的延迟标记向下移动
	int mid = (l + r) >> 1;
	int ret = 0;
	if (L <= mid) //往左走
		ret = max(ret,query(L , R , lson));
	if (mid < R)//往右走
		ret = max(ret,query(L , R , rson));
	return ret;
}
int main() 
{
	int N , M;
	while(~scanf("%d%d",&N,&M))//N为节点数
	{
		build(1 , N , 1); //建树
		while (M--)//M为询问次数
		{
			char op[2];
			int a , b;
			scanf("%s%d%d",op,&a,&b);
			if (op[0] == 'Q') 
			{
				printf("%d\n",query(a , b , 1 , N , 1));
			}
			else
			{
				update(a , b , 1 , N , 1);//把a的成绩更为b
			}
		}
	}
	return 0;
}


你可能感兴趣的:(线段树)