1270. 数列区间最大值 Java题解 (线段树)

输入样例:

10 2
3 2 4 5 6 8 1 2 9 7
1 4
3 8

输出样例:

5
8


解题思路:

题意为找出任意两区间中的最大值,由于询问的次数是百万级的,可以用线段树存储数列的数据:在树的每个结点中维护区间的左右端点和当前区间的最大值,查找时,通过递归实现 logn 的复杂度。总的时间复杂度为 O(mlogn)。

Java代码:

import java.io.*;

public class Main {
	static int []w;
	static Node []tree;
	
	static class Node{
		int l, r;
		int max;
		public Node(int l, int r, int max) {
			this.l = l;
			this.r = r;
			this.max = max;//线段的最大值
		}
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String[] split = br.readLine().split(" ");
		int n = Integer.parseInt(split[0]);
		int m = Integer.parseInt(split[1]);
		w = new int[n + 1];
		split = br.readLine().split(" ");
		for(int i = 1; i <= n; i++)
			w[i] = Integer.parseInt(split[i - 1]);
		tree = new Node[n * 4];
		build(1, 1, n);
		
		StringBuilder ans = new StringBuilder();
		for(int i = 0; i < m; i++) {
			split = br.readLine().split(" ");
			int a = Integer.parseInt(split[0]);
			int b = Integer.parseInt(split[1]);
			ans.append(query(1, a, b) + "\n");
		}
		System.out.print(ans);
	}
	
	public static void pushUp(int u) {
		tree[u].max = Math.max(tree[u << 1].max, tree[u << 1 | 1].max);
	}
	
	public static void build(int u, int l, int r) {
		if(l == r) tree[u] = new Node(l, r, w[l]);//创建叶子结点,结点中只有一个值时,最大值就是这个值
		else {
			tree[u] = new Node(l, r, Integer.MIN_VALUE);//非叶子结点,最大值回溯时判断
			int mid = l + r >> 1;//划分左右儿子
			if(l <= mid) build(u << 1, l, mid);//递归创建左子树
			if(r > mid) build(u << 1 | 1, mid + 1, r);
			pushUp(u);//回溯,求最大值
		}
	}
	
	public static int query(int u, int l, int r) {
		if(l <= tree[u].l && tree[u].r <= r) return tree[u].max;//结点中线段的区间被查询的区间完全覆盖,直接返回最大值
		int mid = tree[u].l + tree[u].r >> 1;//该结点中线段(区间)的中点
		int max = Integer.MIN_VALUE;
		if(l <= mid) max = Math.max(max, query(u << 1, l, r));//做子树中与带查询区间有交集
		if(r > mid) max = Math.max(max, query(u << 1 | 1, l, r));
		return max;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值