hdu-1754 I Hate It【线段树】(求区间最大值)

题目链接:https://vjudge.net/contest/182746#problem/A

I Hate It

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

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

解题分析:

典型的线段树问题,由于数据比较大,所以用查询答案和修改数据都非常快的线段树。      不熟悉线段树的朋友可以看看这篇博客       >>>

以下附代码,以及初学者一些浅薄的理解

#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 2000000;
int n, m, a[MAXN + 5];

struct tree
{
    int l, r;           //每个节点代表一个区间
    int v;              //v表示这个区间内的最大值
}trees[MAXN * 2];       //用数组来实现线段树,2*i代表第i个节点的左儿子,2*i+1代表第i个节点的右儿子

int max(int a, int b){    return a > b ? a : b;}

void buildtree(int rs, int l, int r)   //先从根节点将该线段树建好
{
    trees[rs].l = l;
    trees[rs].r = r;
    if (r == l)
    {
        trees[rs].v = a[l];     //当构建到叶子的时候,该叶子的值为每一个元素对应的值
        return;
    }
    int mid = (l + r) / 2;      //将该区间均分成两部分
    buildtree(rs * 2, l, mid);
    buildtree(rs * 2 + 1, mid + 1, r);
    trees[rs].v = max(trees[rs * 2].v, trees[rs * 2 + 1].v);   //利用递归,一层一层自下而上给每一个节点赋值
}

void update(int rs, int k, int l)
{
    if (trees[rs].l == k && trees[rs].r == k)         //如果找到序号为k的叶子,则将该叶子的值更新为l
    {
        trees[rs].v = l;
        return;
    }
    int mid = (trees[rs].l + trees[rs].r) / 2;       //选择包含序号为k的叶子的路径进行更新,减少不必要的操作
    if (k <= mid)update(rs * 2, k, l);
    if (k>mid)update(rs * 2 + 1, k, l);
    trees[rs].v = max(trees[rs * 2].v, trees[rs * 2 + 1].v);    //利用递归,自下而上的进行更新
}

int querry(int rs, int l, int r)
{
    if (trees[rs].l == l && trees[rs].r == r)         //如果已经找到需要查询的区间,那么直接返回符合该区间的节点对应的值
        return trees[rs].v;
    int mid = (trees[rs].l + trees[rs].r) / 2;
    if (r <= mid)return querry(rs * 2, l, r);         //如果需要查询的区间完全包含在该节点的左儿子内,则顺着该节点的左儿子继续查找
    if (l>mid)return querry(rs * 2 + 1, l, r);
    if (l <= mid && r>mid)
        return max(querry(rs * 2, l, mid), querry(rs * 2 + 1, mid + 1, r));     //如果需要查询的区间一部分在左儿子的区间内,另一部分在右儿子的区间内,则该区间的最大值就在[l,mid]或者[mid+1,r]中取得,比较一下两个区间的最大值即可
    return 0;          //如果不符合条件,则返回0
}

int main()
{
    int i, ac, bc;
    char c;
    while (scanf("%d %d", &n, &m) != EOF)
    {
        for (i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        buildtree(1, 1, n);          //从根节点将线段树建好
        for (i = 1; i <= m; i++)
        {
            getchar();
            scanf("%c%d%d", &c, &ac, &bc);
            if (c == ‘Q‘)
                printf("%d\n", querry(1, ac, bc));      //ac,bc分别为将要查询的区间边界
            else
                update(1, ac, bc);                      //ac表示学生的序号,bc表示该学生更改后的成绩
        }
    }
    return 0;
}

2018-07-19

原文地址:https://www.cnblogs.com/00isok/p/9339152.html

时间: 2024-08-07 14:35:11

hdu-1754 I Hate It【线段树】(求区间最大值)的相关文章

nyoj1185 最大最小值 (线段树求区间最大值和最小值)

对于不懂线段树的,先看为这篇文章理解下.点击打开链接 这道题普通方法 ,TLE. 最大最小值 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给出N个整数,执行M次询问. 对于每次询问,首先输入三个整数C.L.R: 如果C等于1,输出第L个数到第R个数之间的最小值: 如果C等于2,输出第L个数到第R个数之间的最大值: 如果C等于3,输出第L个数到第R个数之间的最小值与最大值的和. (包括第L个数和第R个数). 输入 首先输入一个整数T(T≤100),表示有T组数据.

hdoj 5443 The Water Problem【线段树求区间最大值】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5443 刷道水题助助兴 #include<stdio.h> #include<string.h> #include<algorithm> #include<stack> #define MAX 2100 #define INF 0x7fffff using namespace std; int n,m; int Max[MAX]; void pushup(int

hdu 1754 I Hate It 线段树 点修改

// hdu 1754 I Hate It 线段树 点修改 // // 不多说,裸的点修改 // // 继续练 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #i

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 线段树 点改动

// hdu 1754 I Hate It 线段树 点改动 // // 不多说,裸的点改动 // // 继续练 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #i

hdu 2665 可持久化线段树求区间第K大值(函数式线段树||主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=2665 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The first line is the number of the test cases. For each test case, the first line contain two integer n and m (

HDU 1754 I Hate It(线段树)

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

2016年湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)

原题链接 http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1809 Description Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions. The i-th question is whether P remains balanced after pai and pbi  swapped. Note that questions ar

HDU 1556 Color the ball 线段树更新区间查点

点击打开链接 Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9120    Accepted Submission(s): 4665 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽

HDU6447 YJJ&#39;s Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp

目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:Portal传送门 ?原题目描述在最下面. ?1e5个点,问从(0,0)走到(1e9,1e9)的最大收益. ?当你从(u-1,v-1)走到(u,v)时,你可以获得点(u,v)的权值. Solution: ?十分详细了. ?直接线段树区间最值.当然也可以树状数组,不能st表. ?\(dp[i] = max(query\_max(0,dp[i]-1,1)+val[i] ,