前言:写这篇博客是因为在牛客练习赛68的A题不知道前缀和还可以这么玩,所以就想记录一下前缀和的另一个用法。
正文:题目链接:。对于条件,有n个ai,0≤ai<n 且 ai 互不相同。说明序列是一个值为从0到n-1的n个自然数,(如 n=3, 则无论顺序是什么,序列一定为0,1,2或0,2,1或1,2,0等)。
所以一个区间内最小未出现的自然数就等于不在这个区间内最小出现的自然数。
这个时候就是用到前缀最小值和后缀最小值了
前缀最小值维护的是从初始位置到当前位置的最小值,如pre[4]表示从区间(1,4)的最小值。后缀同理,suf[4]表示从区间(4,n)的最小值
pre[0]=suf[n+1]=n; //pre代表前缀,suf为后缀。 for(int i=1;i<=n;i++) pre[i]=min(pre[i-1],a[i]); for(int i=n;i>=1;i--) suf[i]=min(suf[i+1],a[i]);
我们要找的是不在这个区间(l,r)的最小数,也就是区间(1,l-1)的最小值或区间(r+1,n)的最小值。代码为:min(pre[l-1],suf[r+1])
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<unordered_set>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn =1e5+9;
int a[maxn],pre[maxn],suf[maxn];
int main(){
IOS;
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i];
pre[0]=suf[n+1]=n;
//pre代表前缀,suf为后缀。
for(int i=1;i<=n;i++) pre[i]=min(pre[i-1],a[i]);
for(int i=n;i>=1;i--) suf[i]=min(suf[i+1],a[i]);
while(q--){
int l,r;
cin>>l>>r;
cout<<min(pre[l-1],suf[r+1])<<endl;
}
}
因篇幅问题不能全部显示,请点此查看更多更全内容