Codeforces 1436E. Complicated Computations 题解

题目链接
一开始写了个假算法,没考虑周到就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;
}

猜你喜欢

转载自blog.csdn.net/weixin_45948940/article/details/109273464