题目链接
一开始写了个假算法,没考虑周到就AC了 赛后被叉了
((喜提CF rnk前100 体验卡
题意就是给了我们长度为n的序列 每个元素小于等于n
定义MEX (我就不解释是啥意思了)
博主语文能力水平负十级 - - 不理解还请担待下孩子
现在我们需要做的事
就是找出所有子区间的mex 然后求一次mex的MEX
当时想假了,xjb推理完了以后发现从前往后,从后往前扫一次就OK
实际上会有情况没统计到 (毕竟是假算法)
首先考虑一种划分 , 统计一下每个数的最后一次出现的位置以及上一次出现的位置,然后利用树状数组维护一下这个下标的最小值
首先枚举1到n+1 我们要来找出来这种情况
如果当前我们check mex=i 是否存在, 那么只需要检查 1-- (i-1) 的last值的最小值是不是比 last [i] 还要大 ,因为只要大于它就能保证我们可以得到 mex=i 是不是很显然
然后我们需要逆向更新一次
还是利用上面那个图,如果我们想要得到 mex= i ,题目输入的元素并不是唯一的,那么会有若干个 i 我们只能在每个 i 出现的下标之间判断能不能取到,因为如果是下图这样子check 因为这个区间已经包含了 i 显然得不到mex=i了 所以我们第二次枚举的时候 只需要每次更新a[i] 的前一个出现的下标 然后同理上述 check 一下 a[i]-1 出现的下标的最小值是不是在当前下标的右边
#include<bits/stdc++.h>
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
ll gcd(ll a,ll b){
if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){
bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll lcm(ll a,ll b){
return a*b/gcd(a,b);}
ll qp(ll a,ll b,ll mod){
ll ans=1;if(b==0){
return ans%mod;}while(b){
if(b%2==1){
b--;ans=ans*a%mod;}a=a*a%mod;b=b/2;}return ans%mod;}//快速幂%
ll qpn(ll a,ll b, ll p){
ll ans = 1;a%=p;while(b){
if(b&1){
ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元 (分子*qp(分母,mod-2,mod))%mod;
const int maxl=2e5+7;
ll n,m,cnt;
ll a[maxl],b[maxl],last[maxl],pre[maxl],nxt[maxl];
bool vis[maxl];
inline void upd(int i,int x)
{
while(i<=n+1)
{
b[i]=min(b[i],x);
i+=i&-i;
}
}
inline int getmi(int i)
{
int ret=n+2;
while(i)
{
ret=min(ret,b[i]);
i-=i&-i;
}
return ret;
}
signed main()
{
ll t=1;
while(t--){
read(n);
ll ans=1;
for(int i=1;i<=n+1;i++)
last[i]=0,pre[i]=n+2;
for(int i=1;i<=n;i++)
{
read(a[i]);
pre[i]=last[a[i]];
last[a[i]]=i;
}
for(int i=1;i<=n;i++)
b[i]=n+1;
for(int i=1;i<=n;i++)
upd(i,last[i]);
for(int i=1;i<=n+1;i++){
if(last[i]!=n && getmi(i-1)>last[i])
vis[i]=true;
}
for(int i=n;i>=1;i--)
{
upd(a[i],pre[i]);
if(pre[i]!=i-1 && getmi(a[i]-1)>pre[i])
vis[a[i]]=true;
}
while(vis[ans])
ans++;
printf("%lld\n",ans);
}
return 0;
}