• Tido 习题-二叉树-最高分


    题目描述

    老师想知道从某某同学到某某同学当中,分数最高的是多少。
    现在请你编程模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。

    输入

    输入包含多组测试数据。
    每组输入第一行是两个正整数N和M(0<N<=30000,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。

    输出

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

    样例输入 Copy

    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

    样例输出 Copy

    5
    6
    5
    9


    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<cstring>
    using namespace std;
    const int SIZE=30005;
    int a[SIZE];
    struct SegmentTree{
        int l,r;
        int dat;
    } t[SIZE*4];//struct数组存储线段树
    void build(int p,int l,int r){
        t[p].l=l;t[p].r=r;//节点p表示区间l-r
        if(l==r){
            t[p].dat=a[l];
            return;
        }//叶节点 
        int mid=(l+r)/2;//折半
        build(p*2,l,mid);//左子节点[l,mid],编号p*2 
        build(p*2+1,mid+1,r); //右子节点[mid+1,r],编号p*2+1
        t[p].dat=max(t[p*2].dat,t[p*2+1].dat);//从下往上传递信息 
         
    }
    int ask(int p,int l,int r)//查询区间最大值 
    {
        if(l<=t[p].l&&r>=t[p].r)//完全包含 
            return t[p].dat;
        int mid=(t[p].l+t[p].r)/2;
        int val=-(1<<30);//无穷小 
        if(l<=mid) val=max(val,ask(p*2,l,r));//左子节点有重叠 
        if(r>mid) val=max(val,ask(p*2+1,l,r)); //右子节点有重叠
        return val; 
     } 
    void change(int p,int x,int v){//单点修改
        if(t[p].l==t[p].r){//找到叶节点
                t[p].dat=v;
            return; 
        } 
        int mid=(t[p].l+t[p].r)/2;
        if(x<=mid) change(p*2,x,v);//x属于左半区间 
        else change(p*2+1,x,v); //x属于右半区间
        t[p].dat=max(t[p*2].dat,t[p*2+1].dat);//从下往上更新信息 
    }
    int main()
    {
        int n,m;
        while(cin>>n>>m){
             
            memset(a,0,sizeof(a));
            for(int i=1;i<=n;i++)
                cin>>a[i];
            build(1,1,n);
            for(int i=1;i<=m;i++){
                char c;
                cin>>c;
                int a,b;
                cin>>a>>b;
                if(c=='Q'){
                    cout<<ask(1,a,b)<<endl;
                }
                if(c=='U')
                    change(1,a,b);
            }
        }
        return 0;
    }
    通过线段树可以快速进行单点更新 和 查询区间最大值
    相当于一个非常巧妙的递归
    先从上往下到叶节点
    再将叶节点往上不断进行比较取出最大值
    再从下回到起点
    至于线段树的讲解
    可以先看一下下面的讲解哦
    https://www.cnblogs.com/Tidoblogs/p/10887555.html
     
  • 相关阅读:
    2020.07.01
    2020年5月9日
    2020年4月25日
    2020年4月24日
    2020年4月23日
    2020年4月22日
    2020年3月29日
    2020.3.25
    nacos源码解析(三)-注册中心服务注册处理
    nacos源码解析(二)-客户端如何访问注册中心
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/10887624.html
Copyright © 2020-2023  润新知