//2886又没理解,诶诶,语言障碍
题目描述:给出n个人的升高,有T个询问【i,j】,求从i到j最高-最矮的差。
题解:典型的rmq问题,hankcs用的平方分割(术语称:块状数组),不喜欢,自己打的Square—Table算法,和线段树练练手。
参考程序:
ST:
#include<cstdio>
#include<algorithm>
#define maxn 51000
using namespace std;
int a[maxn];
int n,q;
struct RMQ{
int n;
void init(int n){
this->n=n;
}
int Max[maxn][30];
int Min[maxn][30];
void prepare(){
for (int i=0;i<n;i++)
Max[i][0]=a[i],Min[i][0]=a[i];
for (int j=1;(1<<j)<=n;j++)
for (int i=0;i+(1<<j)<=n;i++){
Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
}
}
int query(int l,int r){
int k=0;
while ((1<<(k+1))<=r-l+1)k++;
int tmax=max(Max[l][k],Max[r-(1<<k)+1][k]);
int tmin=min(Min[l][k],Min[r-(1<<k)+1][k]);
return tmax-tmin;
}
}form;
int main(){
scanf("%d%d",&n,&q);
form.init(n);
for (int i=0;i<n;i++)
scanf("%d",&a[i]);
form.prepare();
while (q--){
int from,to;
scanf("%d%d",&from,&to);
printf("%d\n",form.query(from-1,to-1));
}
return 0;
}
线段树:
#include<cstdio>
#include<algorithm>
#define maxn 51000
#define INF 0x7f7f7f7f
using namespace std;
int n,q;
struct Segment{
int left[3*maxn+10],right[3*maxn+10];
int Max[3*maxn+10],Min[3*maxn+10];
int tmax,tmin;
void build(int no,int l,int r){
int mid=(l+r)>>1;
left[no]=l;right[no]=r;
Max[no]=-INF;Min[no]=INF;
if (l+1<r){
build(2*no,l,mid);
build(2*no+1,mid,r);
}
}
void replace(int no,int l,int data){
if (left[no]+1==right[no]){
Max[no]=max(Max[no],data);
Min[no]=min(Min[no],data);
}else{
int mid=(left[no]+right[no])>>1;
if (l<mid)replace(2*no,l,data);
else replace(2*no+1,l,data);
Max[no]=max(Max[2*no],Max[2*no+1]);
Min[no]=min(Min[2*no],Min[2*no+1]);
}
}
int query_max(int no,int l,int r){
if (l<=left[no] && right[no]<=r){
return Max[no];
}else{
int mid=(left[no]+right[no])>>1;
int tmp=-INF;
if (l<mid)tmp=query_max(2*no,l,r);
if (r>mid)tmp=max(tmp,query_max(2*no+1,l,r));
return tmp;
}
}
int query_min(int no,int l,int r){
if (l<=left[no] && right[no]<=r){
return Min[no];
}else{
int mid=(left[no]+right[no])>>1;
int tmp=INF;
if (l<mid)tmp=query_min(2*no,l,r);
if (r>mid)tmp=min(tmp,query_min(2*no+1,l,r));
return tmp;
}
}
}tree;
int main(){
scanf("%d%d",&n,&q);
tree.build(1,0,n);
for (int i=0;i<n;i++){
int a;
scanf("%d",&a);
tree.replace(1,i,a);
}
while (q--){
int from,to;
scanf("%d%d",&from,&to);
printf("%d\n",tree.query_max(1,from-1,to)-tree.query_min(1,from-1,to));
}
return 0;
}