[藍橋杯][演算法提高VIP]上帝造題五分鐘 (線段樹+區間最小值)

一葉之修發表於2019-03-07

藍橋杯歷年真題題目及題解目錄彙總 

 

題目描述

第一分鐘,上帝說:要有題。於是就有了L,Y,M,C
第二分鐘,LYC說:要有向量。於是就有了長度為n寫滿隨機整數的向量
第三分鐘,YUHCH說:要有查詢。於是就有了Q個查詢,查詢向量的一段區間內元素的最小值
第四分鐘,MZC說:要有限。於是就有了資料範圍
第五分鐘,CS說:要有做題的。說完眾神一鬨而散,留你來收拾此題

輸入

第一行兩個正整數n和Q,表示向量長度和查詢個數
接下來一行n個整數,依次對應向量中元素:a[0],a[1],…,a[n-1]
接下來Q行,每行兩個正整數lo,hi,表示查詢區間[lo, hi]中的最小值,即min(a[lo],a[lo+1],…,a[hi])。

輸出

共Q行,依次對應每個查詢的結果,即向量在對應查詢區間中的最小值。

樣例輸入

7 4
1 -1 -4 8 1 2 -7
0 0
1 3
4 5
0 6

樣例輸出

1
-4
1
-7

提示

第一個查詢[0,0]表示求min{a[0]}=min{1}=1
第二個查詢[1,3]表示求min{a[1],a[2],a[3]}=min{-1,-4,8}=-4
第三個查詢[4,5]表示求min{a[4],a[5]}=min{1,2}=1
第四個查詢[0,6]表示查詢整個向量,求min{a[0..6]}=min{1,-1,-4,8,1,2,-7}=-7

 

沒什麼好解釋啦,目前還處於線段樹入門階段,這題只需要建樹+查詢就好,沒涉及更新

import java.util.Scanner;

public class 藍橋杯_上帝造題五分鐘 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		m = in.nextInt();
		a = new int[n+1];
		tree = new Segtree[4*n+5];
		for(int i=1;i<=n;i++)
			a[i] = in.nextInt();
		for(int i=1;i<=4*n+4;i++)
			tree[i] = new Segtree();
		buildtree(1, 1, n);
		for(int i=1;i<=m;i++)
			System.out.println(query(1, 1, n, in.nextInt()+1, in.nextInt()+1));//注意題目給的是0開頭的下標
	}
	
	static int n,m;
	static Segtree[] tree;
	static int[] a;
	
	static class Segtree {
		int min,l,r;
		public Segtree(int l,int r) {
			this.l = l;
			this.r = r;
		}
		public Segtree() {}
	}
	
	static void buildtree(int now,int l,int r) {
		tree[now].l = l;
		tree[now].r = r;
		if(l==r) {
			tree[now].min = a[l];
			return;
		}
		int mid = l + (r-l)/2;
		buildtree(2*now, l, mid);
		buildtree(2*now+1, mid+1, r);
		tree[now].min = Math.min(tree[2*now].min, tree[2*now+1].min);
	}
	
	static int query(int now,int l,int r,int x,int y) {
		if(y<l || x>r)
			return Integer.MAX_VALUE;
		if(x<=l && y>=r) {
			return tree[now].min;
		}
		
		int mid = l + (r-l)/2;
		return Math.min(query(2*now, l, mid, x, y),query(2*now+1, mid+1, r, x, y));
	}
	
}

 

相關文章