您的位置:首页 > 其它

线段树(二)区间最值

2016-10-10 15:01 176 查看

区间最值

区间求最值是简单的线段树问题,区间最值也可以用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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 区间最值