最小修改次数使数列子串 mex 避开指定值

给定一个长度为 n 的数列 a 和一个整数 k,求最少修改多少个元素,使得数列 a 的任意连续子串的 mex 都不等于 k。

*本题中,数列的 mex 被定义为数列中最小未出现的自然数,例如:

mex'1,2,3'=0,因为 0 是自然数。 mex'0,1,3'=2。 mex'0,1,2'=3。

算法思路:

使用一个栈 st 来维护当前子串的 mex,遍历数列,对于每个元素 a[i],如果 a[i] 等于 k,则清空栈,否则将 a[i] 入栈。每次入栈后,计算当前栈的 mex,并更新最小修改次数。

C++ 代码:

#include <iostream>
#include <cstring>
using namespace std;

const int N = 100005;

int n, k, a[N], st[N], top;

int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> a[i];
    int ans = n;
    for (int i = 1; i <= n; i++)
    {
        if (a[i] == k) top = 0;
        else st[++top] = a[i];
        int mex = 0;
        while (mex <= top && st[mex+1] == mex) mex++;
        ans = min(ans, i - mex);
    }
    cout << ans << endl;
    return 0;
}

代码解析:

  1. 定义数组 a 来存储数列,栈 st 用于维护当前子串的 mex,top 指向栈顶,ans 记录最小修改次数。
  2. 遍历数列 a,对于每个元素 a[i]:
    • 如果 a[i] 等于 k,则清空栈,因为 k 是需要避免的值,所以当前子串的 mex 无法确定。
    • 否则将 a[i] 入栈。
  3. 计算当前栈的 mex:
    • 从 0 开始,依次检查栈中是否有元素等于 mex。
    • 如果有,则 mex++,继续检查下一个元素。
    • 当 mex 大于栈顶元素,或检查完所有元素,则当前栈的 mex 就是 mex。
  4. 更新最小修改次数:
    • 当前子串的最小修改次数为 i - mex,因为只需要修改栈中 mex 之前的元素即可。
    • 将 ans 更新为当前最小修改次数和之前最小修改次数的较小值。
  5. 最后输出 ans,即最小修改次数。
最小修改次数使数列子串 mex 避开指定值

原文地址: https://www.cveoy.top/t/topic/m6R4 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录