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
 

猜你喜欢

转载自www.cnblogs.com/Tidoblogs/p/10887624.html