牛牛的MEX

题目

题目来源
在这里插入图片描述
在这里插入图片描述

思路

因为 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,L1][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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值