AtCoder - abc194_e Mex Min

题目:AtCoder - abc194_e

题意:我们要找到长度为 n 数组 A 的所有的长度为 m 的切片 si 最小的 mex(si) 值。

思路:
可以发现,如果记录切片中每一个数字出现的次数,找到第一个出现次数为0的就是答案。
但是我们不能每次切片改变都去遍历一次,这样会TLE,因此可以用一个数组M维护区间(i,i+m)数字出现的次数。
切片的末尾指向了 Ai 的时候,那么对应的 M a [ i ] M_{a[i]} Ma[i]就会加1;而 M a [ i − m ] M_{a[i-m]} Ma[im] 就会减1。

接下来分情况讨论优化算法效率
1.如果 M a [ i − m ] M_{a[i-m]} Ma[im]==0,且 a i − m a_{i-m} aim<mex,那么可以肯定当前切片的mex值必然为 a i − m a_{i-m} aim
2.如果(1)情况没有发生,且 M m e x M_{mex} Mmex!=0,说明当前切片答案必然不是mex,且大于mex,需向后寻找。
3.如果(1)(2)都不发生,那么mex不变。

code:

#include <bits/stdc++.h>
using namespace std;
#define mos 1500010
#define ll long long
ll n,m;
ll a[mos];
ll flag[mos];
int main()
{
    cin>>n>>m;
    ll ans=1e18;
    for (ll i=0;i<n;i++)
        cin>>a[i];
    for (ll i=0;i<m;i++)
        flag[a[i]]++;//对第一组切片初始化
    ll mex=0;
    for (ll i=0;;i++)//找到第一组切片的mex值
    {
        if (flag[i]==0)
        {   mex=i;
            break;
        }
    }
    ans=min(ans,mex);//这步不能少,不然漏情况
    for (ll i=m;i<n;i++)
    {
        flag[a[i-m]]--;//首元素出队,出现次数--
        flag[a[i]]++;//尾元素出队,出现次数++
        if (flag[a[i-m]]==0 && a[i-m]<mex)//情况1
        {
            mex=a[i-m];
        }
        else if (flag[mex]!=0)//情况2
        {
            while (flag[mex]!=0)
            {
                mex++;
            }
        }
        ans=min(ans,mex);
    }
    cout<<ans<<endl;
    //system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值