#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <math.h>
#include <algorithm>
using namespace std;
const int maxn = 100000;
const int maxm = 30;
//根据题目要求,只需保留用到的就可以了
int d_min[maxn][maxm],d_max[maxn][maxm],a[maxn];
int d_min_indx[maxn][maxm],d_max_indx[maxn][maxm];
int n;//n个数字
//预处理区间最大最小值
void RMQ_init()
{
int i,j;
for(i = 1; i <= n; i++) //数组下标从1开始的。
{
d_min[i][0] = a[i];
d_max[i][0] = a[i];
}
for(j = 1; (1<<j) <= n; j++)
for(i = 1; i + j - 1 <= n; i++)
{
d_min[i][j] = min(d_min[i][j-1],d_min[i + (1<<(j-1))][j-1]);
d_max[i][j] = max(d_max[i][j-1],d_max[i + (1<<(j-1))][j-1]);
}
}
//查询区间最小值
int RMQ_min(int l,int r)
{
int k = 0;
while((1<<(k+1)) <= r-l+1)
k++;
return min(d_min[l][k], d_min[r-(1<<k)+1][k]);
}
//查询区间最大值
int RMQ_max(int l,int r)
{
int k = 0;
while((1<<(k+1)) <= r-l+1)
k++;
return max(d_max[l][k], d_max[r-(1<<k)+1][k]);
}
//预处理区间最大最小值的下标
void RMQ_indx_init(int n,int b[])
{
int i,j;
for(i=0;i<n;i++)
{
d_max_indx[i][0]=i;
d_min_indx[i][0]=i;
}
for(j=1;(1<<j)<=n;j++)
for(i=0;i+(1<<j)-1<n;i++)
{
d_min_indx[i][j]=b[d_min_indx[i][j-1]] < b[d_min_indx[i+(1<<(j-1))][j-1]]? d_min_indx[i][j-1]:d_min_indx[i+(1<<(j-1))][j-1];
d_max_indx[i][j]=b[d_max_indx[i][j-1]] > b[d_max_indx[i+(1<<(j-1))][j-1]]? d_max_indx[i][j-1]:d_max_indx[i+(1<<(j-1))][j-1];
}
}
//查询区间最大值的下标
int RMQ_indx_max(int s,int v,int b[])
{
int k=(int)(log((v-s+1)*1.0)/log(2.0));
return b[d_max_indx[s][k]]>b[d_max_indx[v-(1<<k)+1][k]]? d_max_indx[s][k]:d_max_indx[v-(1<<k)+1][k];
}
//查询区间最小值的下标
int RMQ_indx_min(int s,int v,int b[])
{
int k=(int)(log((v-s+1)*1.0)/log(2.0));
return b[d_min_indx[s][k]]<b[d_min_indx[v-(1<<k)+1][k]]? d_min_indx[s][k]:d_min_indx[v-(1<<k)+1][k];
}
int main()
{
int i,l,r;
cin>>n;
for(i = 1; i <= n; i++) //数组下标从1开始的。
cin>>a[i];
RMQ_init();
RMQ_indx_init(sizeof(a)/sizeof(a[0]),a);
while(cin>>l>>r)
{
cout<<"最小值:"<<RMQ_min(l,r)<<" 下标:"<<RMQ_indx_min(l,r,a)<<endl;
cout<<"最大值:"<<RMQ_max(l,r)<<" 下标:"<<RMQ_indx_max(l,r,a)<<endl;
}
return 0;
}
(RMQ)求区间最值及其下标 模板
最新推荐文章于 2023-10-05 08:59:09 发布