HDU 1754 I Hate It(线段树+单点更新)

 

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
 
注:这是一道线段树的入门题,主要了解其基本的操作。
 
 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 const int MAXN = 200005;
 8 struct data
 9 {
10     int left, right, Max;
11 } tree[3*MAXN];
12 int score[MAXN];
13 void pushUp(int node)
14 {
15     tree[node].Max = max(tree[2*node].Max, tree[2*node+1].Max);
16 }
17 void build(int left, int right, int node)   //构建线段树
18 {
19     //当前节点所表示的区间  
20     tree[node].left = left;
21     tree[node].right = right; 
22     //左右区间相同,则此节点为叶子,Max 应储存对应某个学生的值
23     if (left == right){
24         tree[node].Max = score[left];
25         return;
26     }
27     //递归建立左右子树
28     int mid = left + (right - left) / 2;
29     build(left, mid, 2*node);
30     build(mid+1, right, 2*node+1);
31     //从子树中获得最大值
32     pushUp(node);
33 }
34 int query(int left, int right, int node)    //查询区间[left,right]的Max值
35 {
36     //所查区间不在范围内
37     if (tree[node].left > right || tree[node].right < left)
38         return 0;
39     //所查区间包含当前节点所管理的区间
40     if (left <= tree[node].left && tree[node].right <= right)  
41         return tree[node].Max;
42     int mid = (tree[node].left + tree[node].right) / 2;
43     //所查区间与当前节点所管理的区间有部分相交
44     if (right <= mid)
45         return query(left, right, 2*node);
46     else if (left > mid)
47         return query(left, right, 2*node+1);
48     else
49         return max(query(left, right, 2*node), query(left, right, 2*node+1));
50 }
51 void Updata(int pos, int val, int node)     //更新pos点的值
52 {
53     //更新当前节点的Max值
54     tree[node].Max = max(val, tree[node].Max);
55     //pos点为叶子节点
56     if (tree[node].left == pos && tree[node].right == pos){
57         tree[node].Max = val;
58         return;
59     }
60     if (pos <= tree[2*node].right)
61         Updata(pos, val, 2*node);
62     else
63         Updata(pos, val, 2*node+1);
64 }
65 int main()
66 {
67     int n, m;
68     while (~scanf("%d %d", &n, &m)){
69         for (int i=1; i<=n; i++)
70             scanf("%d", &score[i]);
71         build(1, n, 1);
72         char c;
73         int a, b;
74         for (int i=1; i<=m; i++){
75             getchar();
76             scanf("%c %d %d", &c, &a, &b);
77             if (c == 'U')
78                 Updata(a, b, 1);
79             else
80                 printf("%d\n", query(a, b, 1));
81         }
82     }
83     return 0;
84 }
View Code

 

转载于:https://www.cnblogs.com/hgfblog/p/4682200.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值