最高分是多少--线段树T1

来源:JK老班

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

输入:

输入包含多组测试数据。
每组输入第一行是两个正整数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。

输出:

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

样例输入:

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

样例输出:

5
6
5
9


线段树建立:数组    或    二叉树的链式结构。

一般不是完全二叉树,不用数组,因为会浪费较多空间,但只有最后一层不是,也可以尝试,浪费不是很多。

链式二叉树,不用递归,难建,尤其是任意二叉树,完全二叉树还好些。

递归:只管你这层怎么做。

 

  • 前半部分,递归,建好左子树,挂上来;
  • 后半部分,递归,建好右子树,挂上来。

 

线段,是不是这个节点表示的:

  • 是,return;
  • 不是,三种情况。完全落在左半部分,去左孩子;完全落在右半部份,去右孩子;左,右都有分布,拆成2部分往下传。

 

import java.util.Scanner;

public class P1566 {

    int[] A;
    BTNode root;
    
    public P1566(){
        Scanner sc=new Scanner(System.in);
        
        while(sc.hasNextInt()) {
            int N=sc.nextInt(),    M=sc.nextInt();
            A=new int[N];
            for(int i=0;i<N;i++) A[i]=sc.nextInt();
            root=Build(0,N-1);
            
            for(int i=0;i<M;i++) {
                String C=sc.next();    int a=sc.nextInt();    int b=sc.nextInt();
                if(C.equals("Q")) System.out.println(Query(a-1,b-1,root));
                else Update(a-1,b,root);
            }
        }
        
    }
    
    //用递归建立二叉树
    BTNode Build(int start,int end) {//返回根节点,参数为当前线段起点和终点
        BTNode current=new BTNode();
        current.L=start;    current.R=end;
        
        //线段就1个元素时
        if(start==end) {
            current.MAX=A[start];
            return current;
        }
        
        int mid=(start+end)/2;
        //建左右子树
        current.left=Build(start,mid);//返回的根节点是左孩子
        current.right=Build(mid+1,end);//返回的根节点是右孩子
        current.MAX=Math.max(current.left.MAX, current.right.MAX);
        return current;
        
    }
    
    int Query(int start,int end,BTNode current) {//要查的线段,现在在哪个节点
        //你要查的线段是不是我这个节点表示的线段?
        
        //是,直接返回
        if(start==current.L && end==current.R) return current.MAX;
        
        //不是,就有3种情况
        int mid=(current.L+current.R)/2;
        if(end<=mid) return Query(start,end,current.left);//1.要查的线段全在(当前节点表示的线段的)左孩子,往左
        if(start>mid) return Query(start,end,current.right);//2.要查的线段全在右孩子,往右
        return Math.max(Query(start,mid,current.left), Query(mid+1,end,current.right));//3.要查的线段左右都有分布,拆分
        
    }
    
    void Update(int index,int newValue,BTNode current) {
        if(current.L==index && current.R==index) {
            current.MAX=newValue;
            return;
        }
        int mid=(current.L+current.R)/2;
        if(index<=mid) Update(index,newValue,current.left);
        else Update(index,newValue,current.right);
        current.MAX=Math.max(current.left.MAX, current.right.MAX);
    }
    
    public static void main(String[] args) {
        P1566 p=new P1566();
    }

    class BTNode{//线段树的节点
        int L,R;//线段
        int MAX;//这个线段的最大值
        BTNode left,right;//左右孩子
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值