您的位置:首页 > 其它

poj 3264 Balanced Lineup(一维RMQ)

2015-08-17 16:33 573 查看
题意:每次操作求区间[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
;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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: