题目
思路
因为 a [ i ] a[i] a[i]各不相同,比如我们当前要求 [ L , R ] [L,R] [L,R],那么我们只需要取 [ 1 , L − 1 ] 和 [ R + 1 , n ] [1,L-1]和[R+1,n] [1,L−1]和[R+1,n]的最小值即可;
Code1
可以用前缀最小值 + 后缀最小值来完成;
#include <iostream>
using namespace std;
const int N = 1e5+10;
int mnL[N],mnR[N],a[N];
int n,q;
int main(){
cin >> n >> q;
for(int i=1;i<=n;++i) cin >> a[i];
int l,r;
mnL[0] = n;
mnR[n+1] = n;
for(int i=1;i<=n;++i) mnL[i] = min(mnL[i-1],a[i]);
for(int i=n;i>=1;--i) mnR[i] = min(mnR[i+1],a[i]);
while(q--){
cin >> l >> r;
cout << min(mnL[l-1],mnR[r+1]) << '\n';
}
return 0;
}
Code2
也可以维护一个ST表来实现
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
const int N = 1e5+10;
int a[N],f[N][70];
int n,q;
void init(){
memset(f,0x3f,sizeof f);
int k = log2(n);
for(int j=0;j<=k;++j){
for(int i=1;i+(1<<j)-1<=n;++i){
if(j == 0) f[i][j] = a[i];
else f[i][j] = min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r){
if(l > r) return 0x3f3f3f3f;
int k = log2(r-l+1);
return min(f[l][k],f[r-(1<<k)+1][k]);
}
int main(){
cin >> n >> q;
for(int i=1;i<=n;++i) cin >> a[i];
int l,r,ans;
init();
while(q--){
cin >> l >> r;
ans = min(query(1,l-1),query(r+1,n));
ans = min(ans,n);
cout << ans << '\n';
}
return 0;
}
Code3
离线的线段树也是可以的;
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
const int N = 1e5+10;
int a[N];
struct Node{
int l,r,mn;
}tr[N<<2];
int n,q;
#define lc (p<<1)
#define rc (p<<1|1)
void push_up(int p){
tr[p].mn = min(tr[lc].mn,tr[rc].mn);
}
void build(int p,int l,int r){
tr[p].l = l,tr[p].r = r;
if(l == r){
tr[p].mn = a[l];
return;
}
int mid = (l+r) >> 1;
build(lc,l,mid);
build(rc,mid+1,r);
push_up(p);
}
int query(int p,int l,int r){
if(l > r) return 0x3f3f3f3f;
if(tr[p].l>=l&&tr[p].r<=r){
return tr[p].mn;
}
int mid = (tr[p].l+tr[p].r) >> 1;
if(r<=mid){
return query(lc,l,r);
}else if(l>mid){
return query(rc,l,r);
}else{
return min(query(lc,l,mid),query(rc,mid+1,r));
}
}
int main(){
cin >> n >> q;
for(int i=1;i<=n;++i) cin >> a[i];
int l,r,ans;
build(1,1,n);
while(q--){
cin >> l >> r;
ans = min(query(1,1,l-1),query(1,r+1,n));
ans = min(ans,n);
cout << ans << '\n';
}
return 0;
}