码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3264 Balanced Lineup(一维RMQ)

时间:2015-08-17 17:15:10      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:

题意:每次操作求区间[L,R]中最大值与最小值之差;

参考:http://blog.csdn.net/liang5630/article/details/7917702

思路:可以用线段树写,但ST算法求RMQ更方便;

        dp[i][j]表示从第i个数开始到i+2^j中的最值;

        在操作之前,预处理出每段区间的最值,采用二分区间求极值的思想,降低复杂度;

         查询时,覆盖查询区间,长度R-L+1,对于dp中,j=log(R-L+1),在这段区间中二分区间求极值即可;

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int dpmax[300010][30];
int dpmin[300010][30];
int num[500010],mm[500010];
void init_rmq(){
    mm[0]=-1; //用于计算log
    for(int i=1;i<=n;i++){
        mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1];
        dpmax[i][0]=num[i];
        dpmin[i][0]=num[i];
    }
    for(int j=1;j<=mm[n];j++) //枚举长度
        for(int i=1;i+(1<<j)-1<=n;i++) //枚举起点
        {
            dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]);
            dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]);
        }
}
int rmqmax(int x,int y){
    int k=mm[y-x+1]; //覆盖查询区间所需的长度
    return max(dpmax[x][k],dpmax[y-(1<<k)+1][k]);
}
int rmqmin(int x,int y){
    int k=mm[y-x+1];
    return min(dpmin[x][k],dpmin[y-(1<<k)+1][k]);
}
int main(){
   int i,j,k,u,v;
   while(scanf("%d%d",&n,&m)!=EOF){
     for(i=1;i<=n;i++) scanf("%d",&num[i]);
     init_rmq();
     for(i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        int t1=rmqmax(u,v);
        int t2=rmqmin(u,v);
        printf("%d\n",t1-t2);
     }
   }
   return 0;
}

 

poj 3264 Balanced Lineup(一维RMQ)

标签:

原文地址:http://www.cnblogs.com/dominatingdashuzhilin/p/4736970.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!