線段樹(二)區間最值

區間最值

區間求最值是簡單的線段樹問題,區間最值也可以用ST表求得,具體問題具體分析.
思想
考慮建樹
遞歸建樹,葉節點的最值就是當前節點表示的值
除葉節點外的其他節點最值等於Max(左兒子,右兒子)或是Min(左兒子,右兒子);
給出某個區間後將這個區間分到很多子區間快速求解
舉個栗子,還是上一節的[1,10]的樹,現在詢問[4,7]的最值
由於左右兒子是根據Mid分開的,所以在分配問題時也需要考慮Mid和給定區間的關係
1.左端點大於Mid
代表整個區間在右兒子上,只需詢問右兒子
2.右端點小於Mid
代表整個區間在左兒子上,只需詢問左兒子
3.跨越左右兒子
在左右兒子的最值取Max或Min
遞歸可求解,複雜度NlogN
代碼
#include<cstdio>
#include<iostream>
#include<iostream>
using namespace std;
const int Maxn=100001;
#define mid (l+r)/2
#define lc o<<1
#define rc (o<<1)+1

struct node{int mi;}point[Maxn*4];

int t,n,x,y,a[Maxn];

int query(int l,int r,int o,int x,int y)
{
	if(l==r)return point[o].mi;
	if(x==l&&y==r) return point[o].mi;
	else if(y<=mid) return query(l,mid,lc,x,y);
	else if(x>mid) return query(mid+1,r,rc,x,y);
	else return min(query(l,mid,lc,x,mid),query(mid+1,r,rc,mid+1,y));
}

void build(int l,int r,int o)
{
	if(l==r){point[o].mi=a[l];return;}
	build(l,mid,lc);
	build(mid+1,r,rc);
	point[o].mi=min(point[lc].mi,point[rc].mi);
	return;
}

int main()
{
	scanf("%d%d",&n,&t);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	build(1,n,1);
	for(int i=1;i<=t;i++)
	{
		scanf("%d%d",&x,&y);
		printf("%d ",query(1,n,1,x,y));
	}
}


區間最大值把Min操作改成Max即可
End。
發佈了55 篇原創文章 · 獲贊 15 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章