非全包含

代码注释与解题思路

解题思路

这道题目要求我们找到一个序列A,通过移除末尾元素的操作,使得序列不再包含1到M的所有整数。我们需要找出最少需要移除多少个末尾元素才能满足这个条件。

关键思路:

  1. 检查初始状态:首先判断原始序列是否已经不符合条件(即不包含1到M的所有整数)
  2. 寻找临界点:如果初始符合条件,则找到从后往前第一个使得序列不再包含1到M所有整数的位置
  3. 计算操作次数:根据找到的临界点计算需要移除的元素数量

代码注释

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N  = 1e2+5;  // 定义常量N为105,足够容纳最大输入规模

int n, m;       // n表示序列长度,m表示需要检查的整数范围1-m
int x, vis[N];   // x用于临时存储输入的数字,vis数组标记1-m中哪些数字已经出现过

int main(){
    // 输入序列长度n和范围m
    cin>>n>>m;
    
    int flag = 0;  // flag记录最后一个满足"包含1-m所有数"的位置
    
    for(int i=1;i<=n;i++){
        cin>>x;     // 读入当前数字
        vis[x] = 1; // 标记该数字已出现
        
        // 检查1到m的所有数字是否都已出现
        for(int j=1;j<=m;j++){
            if(vis[j]==0){
                // 如果发现缺失的数字,更新flag为当前位置i
                flag = i; // 到第i个数还不满足包含1-m所有数
                break;
            }
        }
    }
    
    // 输出结果:总长度n减去最后一个满足条件的位置flag
    // 即需要移除n-flag个末尾元素才能使条件不成立
    cout<<n-flag; 
    
    return 0;
}

代码解析

  1. 初始化

    • 定义数组vis用于记录1到m的数字是否出现过
    • flag变量初始化为0,用于记录关键位置
  2. 遍历输入序列

    • 逐个读取数字并标记其出现
    • 每次读取后检查1到m的所有数字是否都已出现
    • 如果发现缺失,则更新flag为当前位置
  3. 计算结果

    • n-flag表示需要移除的末尾元素数量
    • 如果初始就不满足条件,flag等于n,输出0
    • 如果全部满足,flag为0,需要移除全部n个元素

示例分析

样例1
输入:

5 3
3 2 3 1 2

处理过程:

  1. 读取3,vis[3]=1,flag=1
  2. 读取2,vis[2]=1,flag=2
  3. 读取3,vis不变,flag=3
  4. 读取1,vis[1]=1,此时1-3都已出现,flag不更新
  5. 读取2,vis不变
    最终flag=3(位置3时首次满足条件),输出5-3=2

样例2
输入:

4 3
1 3 1 3

处理过程:

  1. 读取1,vis[1]=1,flag=1
  2. 读取3,vis[3]=1,flag=2
  3. 读取1,vis不变,flag=3
  4. 读取3,vis不变
    始终缺少2,flag保持更新到最后为4,输出4-4=0

该算法高效地通过一次遍历即可确定结果,时间复杂度为O(n*m),在题目约束下完全可行。

posted @ 2025-05-11 12:08  季风起  阅读(4)  评论(0)    收藏  举报