很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。这让很多学生很反感。
不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N N N 和 M ( 0 < N ≤ 200000 , 0 < M < 5000 ) M ( 0
学生 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;
}