题目链接:http://poj.org/problem?id=3264
先说题意,先给出一个一维数组,然后求任意给定的区间内最大值和最小值的差。
典型的RMQ (Range Minimum/Maximum Query)问题,解题思路种类比较多。
此处用的是ST算法:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXN 50050
int num[MAXN];
int f1[MAXN][100],f2[MAXN][100];
void ST(int n){
int k,m;
k=(int)(log((double)n)/log(2.0));
for(int i=0;i<n;i++){//初值赋予
f1[i][0]=num[i];
f2[i][0]=num[i];
}
for(int j=1;j<=k;j++){
for(int i=0;i+(1<<j)-1<n;i++){
m=i+(1<<(j-1));//m的值是上一个区间的尾数+1
f1[i][j]=max(f1[i][j-1],f1[m][j-1]);//上两个区间的左区间和右区间
f2[i][j]=min(f2[i][j-1],f2[m][j-1]);
}
}
}
void rmq(int A,int B){
int t1,t2;
int C=(int)(log((double)(B-A+1))/log(2.0));
t1=max(f1[A][C],f1[B-(1<<C)+1][C]);
t2=min(f2[A][C],f2[B-(1<<C)+1][C]);
printf("%d\n",t1-t2);
}
int main(){
int N,Q,A,B;
while(~scanf("%d%d",&N,&Q)){
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
for(int i=0;i<N;i++)
scanf("%d",&num[i]);
ST(N);//构建ST数组
while(Q--){
scanf("%d%d",&A,&B);
rmq(A-1,B-1);
}
}
return 0;
}
表示今天又被师父提问憋题了,题目跟此题类似,只要求求出某区间内最大值,要求不可以用线段树。
和另一个徒弟废了半天劲YY出了树状数组的做法,不过代码依旧写不出来。与此同时才发现自己对二进制的掌握和二进制数的熟悉真是差到极点,见到32767也没什么反应,为了以后能够做到全面(比如状态压缩),表示只能硬着头皮继续了。