Balanced Lineup-POJ - 3264-RMQ线段树/st表

题目是经典 查询区间最值问题 

可以用RMQ线段树,或者st表

rmq线段树 建树 查询都是logn   支持更新元素

 st表建树logn 查询o(1)!    不支持更新元素

以下是st表代码

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
 
 
const int maxn=50005;
 int h[maxn];
 int mx[maxn][16],mn[maxn][16];
int n,q;
int max(int a,int b)
{
	if (a<b)
	return b;
	return a;
} 
int min(int a,int b)
{
	if (a>b)
	return b;
	return a;
}
 void rmq_init()
 {
     int i,j;
     for(j=1;j<=n;j++) mx[j][0]=mn[j][0]=h[j];
     int m=floor(log((double)n)/log(2.0));
     for(i=1;i<=m;i++){
         for(j=n;j>0;j--){
             mx[j][i]=mx[j][i-1];
             if(j+(1<<(i-1))<=n) mx[j][i]=max(mx[j][i],mx[j+(1<<(i-1))][i-1]);
         }
    }
    for(i=1;i<=m;i++){
         for(j=n;j>0;j--){
            mn[j][i]=mn[j][i-1];
             if(j+(1<<(i-1))<=n) mn[j][i]=min(mn[j][i],mn[j+(1<<(i-1))][i-1]);
         }
     }
 }
 
 int rmq_max(int l,int r)
 {
     int m=floor(log((double)(r-l+1))/log(2.0));
    int a=max(mx[l][m],mx[r-(1<<m)+1][m]); 
    return a;   //a为最大值,b为最小值
 }
 int rmq_min(int l,int r)
 {
     int m=floor(log((double)(r-l+1))/log(2.0)); 
     int b=min(mn[l][m],mn[r-(1<<m)+1][m]);
    return b;   //a为最大值,b为最小值
 }
 int main()
 {
int i,a,b;

	 cin>>n>>q;
	 for (i=1;i<=n;i++)
		 cin>>h[i]; 
	 rmq_init();
	
	 for (i=1;i<=q;i++)
	 {
		 scanf("%d%d",&a,&b);
	 printf("%d\n",rmq_max(a,b)-rmq_min(a,b ));
	 }
	 return 0;
 }



以下是线段树代码:

 


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#define  inf 0x7fffffff
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 50005;

int st_min[maxn<<2],st_max[maxn<<2];
int aa[maxn];
inline int minn(int a,int b) { return a>b?b:a; }
inline int maxx(int a,int b) { return a>b?a:b; }
void PushUP(int rt)
{
    st_min[rt] = minn(st_min[rt<<1],st_min[rt<<1|1]);
    st_max[rt] = maxx(st_max[rt<<1],st_max[rt<<1|1]);
}
int  ok=0;
void build(int l,int r,int rt) {
    if (l == r)
    {	 st_min[rt]=aa[++ok];		
        st_max[rt] = st_min[rt];
        return ;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUP(rt);
}

int query_min(int L,int R,int l,int r,int rt) 
{
    if (L <= l && r <= R) {
        return st_min[rt];
    }
    int m = (l + r) >> 1;
    int ret1 = inf,ret2 = inf;
    if (L <= m) ret1 = query_min(L , R , lson);
    if (R > m) ret2 = query_min(L , R , rson);
    return minn(ret1,ret2);
}
int query_max(int L,int R,int l,int r,int rt) 
{
    if (L <= l && r <= R) {
        return st_max[rt];
    }
    int m = (l + r) >> 1;
    int ret1 = -inf,ret2 = -inf;
    if (L <= m) ret1 = query_max(L , R , lson);
    if (R > m) ret2 = query_max(L , R , rson);
    return maxx(ret1,ret2);
}

int main(void)
{
    int n,m,i,a,b;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
		for (i=1;i<=n;i++) 
        scanf("%d",&aa[i]);

        build(1 , n , 1);
        for(i=1;i<=m;i++)
        {
			scanf("%d %d",&a,&b);
            printf("%d\n",query_max(a,b,1,n,1)-query_min(a,b,1,n,1) );
        } 
    }
    return 0;
}



                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值