【HDU】1754 I hate it ——线段树 单点更新 区间最值

I Hate It

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 37448    Accepted Submission(s): 14816

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

题解:很明显,这是一道线段树的单点更新求区间最值的一道题,单点更新倒是十分好办的,使用update函数更新到单点就可以了,关键是这个求区间最值的问题,假若最后查询的时候再计算这个最值,所花费的时间恐怕比直接暴力费时还要多,所以这题的正确解决方法是在update的时候顺便更新所有经过的节点的值。

AC代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 const int LEN = 200020;
 7
 8 struct line
 9 {
10     int left;
11     int right;
12     int ma;
13 }line[LEN*5];
14
15 void buildt(int l, int r, int step)  //建树,同时初始化区间最值
16 {
17     line[step].left = l;
18     line[step].right = r;
19     line[step].ma = 0;
20     if (l == r)
21         return;
22     int mid = (l + r) / 2;
23     buildt(l, mid, step*2);
24     buildt(mid+1, r, step*2+1);
25 }
26
27 int update(int l, int r, int value, int step)  //更新函数,返回整型
28 {
29     if (line[step].left == line[step].right){  //如果到达最深处的节点,则说明找到了需要更新的单点,赋值
30         line[step].ma = value;
31         return max(line[step/2*2].ma, line[step/2*2+1].ma); //返回该节点与其兄弟节点的较大值
32     }
33     int mid = (line[step].left + line[step].right) / 2;  //向下继续搜索
34     if (r <= mid)
35         line[step].ma = update(l, r, value, step*2);
36     else if (l > mid)
37         line[step].ma = update(l, r, value, step*2+1);
38     else{             //如果目标线段处于目前线段的中点的两边,则同时搜索该节点的两个子节点,并取较大值
39         line[step].ma = max(update(l, mid, value, step*2), update(mid+1, r, value, step*2+1));
40     }
41     return max(line[step/2*2].ma, line[step/2*2+1].ma);  //返回该节点与其兄弟节点的较大值
42 }
43
44 int dfs(int l, int r, int step)  //dfs找答案
45 {
46     if (l == line[step].left && r == line[step].right) //如果找到目标区间,返回值
47         return line[step].ma;
48     int mid = (line[step].left + line[step].right) / 2;
49     if (r <= mid)
50         return dfs(l, r, step*2);
51     else if (l > mid)
52         return dfs(l, r, step*2+1);
53     else{
54         return max(dfs(l, mid, step*2), dfs(mid+1, r, step*2+1)); //返回该节点与其兄弟节点的较大值
55     }
56 }
57
58
59 int main()
60 {
61     int n, m;
62     //freopen("in.txt", "r", stdin);
63     while(scanf("%d %d", &n, &m) != EOF){
64         buildt(1, n, 1);
65         for(int i = 1; i <= n; i++){
66             int t;
67             scanf("%d", &t);
68             update(i, i, t, 1);
69         }
70         for(int i = 0; i < m; i++){
71             char query[2];
72             int a, b;
73             scanf("%s %d %d", query, &a, &b);
74             if (query[0] == ‘U‘)
75                 update(a, a, b, 1);
76             else if (query[0] == ‘Q‘){
77                 printf("%d\n", dfs(a, b, 1));
78             }
79         }
80     }
81     return 0;
82 }

【HDU】1754 I hate it ——线段树 单点更新 区间最值

时间: 2024-08-01 22:43:05

【HDU】1754 I hate it ——线段树 单点更新 区间最值的相关文章

HDU 1754 I Hate It 线段树 单点更新 区间最大值

1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstdio> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<cstring> 10 #include<stack> 11 #

hdu 1754 I Hate It 线段树单点更新和区间求和

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 参照HH大牛写的额! Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多

HDU 1754 I Hate It 线段树单点更新求最大值

题目链接 线段树入门题,线段树单点更新求最大值问题. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define N 200005 using namespace std; int data[N]; struct Tree { int l,r,ans; }tree[N*4]; void build(in

hdu2795(线段树单点更新&amp;区间最值)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:有一个 h * w 的板子,要在上面贴 n 条 1 * x 的广告,在贴第 i 条广告时要尽量将其靠上贴,并输出其最上能贴在哪个位置: 思路:可以将每行剩余空间大小存储到一个数组中,那么对于当前 1 * x 的广告,只需找到所有剩余空间大于的 x 的行中位置最小的即可: 不过本题数据量为 2e5,直接暴力因该会 tle.可以用个线段树维护一下区间最大值,然后查询时对线段树二分即可: 代码

HDU 1754 I Hate It 线段树(单点更新,成段查询)

题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=1754 题解: 单点更新,成段查询. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lson o<<1 6 #define rson (o<<1)|1 7 #define M l+(r

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

http://acm.hdu.edu.cn/showproblem.php?pid=1754 照着hdu 1166 的模板稍加改动即可 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int sum[1000000]; void push(int rt) { sum[rt]=max(sum[rt<<1],s

HDU 1754 I Hate It (线段树单点更新求最大值RMQ)

I Hate It Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多组测试,请处理到文件结束.在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目.学生ID编号分别从1

hdu 3308 线段树单点更新 区间合并

http://acm.hdu.edu.cn/showproblem.php?pid=3308 学到两点: 1.以区间端点为开始/结束的最长......似乎在Dp也常用这种思想 2.分类的时候,明确标准逐层分类,思维格式: 条件一成立: { 条件二成立: { } else { } } else { 条件二成立: { } else { } } 上面的这种方式很清晰,如果直接想到那种情况iif(条件一 &条件二)就写,很容易出错而且把自己搞乱,或者情况不全,,,我就因为这WA了几次 3.WA了之后 ,

HDU 1166 敌兵布阵(线段树单点更新,板子题)

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 87684    Accepted Submission(s): 36912 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务