HDU-1754 I Hate It(线段树单点更新,维护区间最大值)

文章目录

  • 题目描述
    • 输入格式
    • 输出格式
    • 样例输入
    • 样例输出
    • 提交链接
    • 提示
  • 解析
  • 参考代码

题目描述

很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。这让很多学生很反感。

不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。

输入格式

本题目包含多组测试,请处理到文件结束。

在每个测试的第一行,有两个正整数 N N N M ( 0 < N ≤ 200000 , 0 < M < 5000 ) M ( 0M(0<N200000,0<M<5000),分别代表学生的数目和操作的数目。

学生 ID 编号分别从 1 1 1 编到 N N N

第二行包含 N N N 个整数,代表这 N N N 个学生的初始成绩,其中第 i i i 个数代表 ID 为 i i i 的学生的成绩。

接下来有 M M M 行。每一行有一个字符 C C C (只取 ′ Q ′ 'Q' Q ′ U ′ 'U' U ) ,和两个正整数 A A A B B B

C C C ′ Q ′ 'Q' Q 的时候,表示这是一条询问操作,它询问 ID 从 A A A B B B (包括 A , B A,B A,B)的学生当中,成绩最高的是多少。

C C C ′ U ′ 'U' U 的时候,表示这是一条更新操作,要求把 ID 为 A A A 的学生的成绩更改为 B B B

输出格式

对于每一次询问操作,在一行里面输出最高成绩。

样例输入

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

样例输出

5
6
5
9

提交链接

https://acm.hdu.edu.cn/showproblem.php?pid=1754

提示

大量输入,scanf() 将比 cin 更好地工作。

样例解释:
5 个数分别为 1 2 3 4 5,6 次询问。
Q 1 5,询问区间 [1,5] 的最大值,输出的结果为 5。
U 3 6 ,将 id 为 3 的学生的成绩改为 6,改完之后的 5 个数为 1 2 6 4 5
Q 3 4,询问区间 [3,4] 的最大值,输出的结果为 6。
Q 4 5,询问区间 [4,5] 的最大值,输出的结果为 5。
U 2 9,将 id 为 2 的学生的成绩改为 9,改完之后的 5 个数为 1 9 6 4 5
Q 1 5,询问区间 [1,5] 的最大值,输出的结果为 9。

解析

单点更新,不需要懒惰标记。
建树,更新操作,询问操作。

参考代码

#include
#include
#include
using namespace std;
const int maxn = 8e5 + 9;
int mx[maxn << 2] , a[maxn];
int n , m;
void build(int l , int r , int k)
{
	if(l == r)   //叶子结点
	{
		mx[k] = a[l];
		return;
	}
	int mid = (l + r) >> 1; 
	build(l , mid , k << 1);  //左子树 
	build(mid + 1 , r , k << 1 | 1);  //右子树 
	mx[k] = max(mx[k << 1] , mx[k << 1 | 1]);
}
void update(int pos , int target , int l , int r , int k)
{
	if(l == r)
	{
		mx[k] = target;
		return;
	}
	int mid = (l + r) >> 1;
	if(pos <= mid)
		update(pos , target , l , mid , k << 1);
	else
		update(pos ,  target , mid + 1 , r ,  k << 1 | 1);
	mx[k] =  max(mx[k << 1] , mx[k << 1 | 1]);
} 
int  query(int x , int y , int l , int r , int k)
{
	if(x <= l && y >= r) // x l r y 
		return mx[k];
	int mid = (l  + r) >> 1;
	if(y <= mid)
		return query(x , y , l , mid , k << 1);
	if(x > mid)
		return query(x , y , mid + 1 , r , k << 1 | 1);
	return max(query(x , y , l , mid , k << 1) , query(x , y , mid + 1 , r , k << 1 | 1));
}
int main()
{
	while(~scanf("%d%d" , &n , &m))
	{
		memset(mx , 0 , sizeof(mx));
		for(int i = 1; i <= n; i++)
			scanf("%d" , &a[i]);
		build(1 , n , 1);  //建树
		char op[2];
		int a , b;
		while(m--)
		{
			scanf("%s%d%d",op , &a , &b);
			if(op[0] == 'Q')
				printf("%d\n" , query(a , b , 1 , n , 1));   //询问 [a,b] 之间的最大值
			else
				update(a , b , 1 , n , 1);     //id 为 a 的学生的成绩改为 b 
		}
	}
	return 0;
}

你可能感兴趣的:(#,线段树,算法,数据结构,信息学奥赛,程序设计竞赛,线段树)