首页 > 其他分享 >MEX_Destruction

MEX_Destruction

时间:2025-01-07 12:01:25浏览次数:5  
标签:arr int number start vector array MEX Destruction

题目描述

  对于给定的数组(a1,a2,a3...an),选择其中的任意子数组(ai,ai+1...aj),将其用MEX[1] (ai,ai+1...aj)代替。那么最少需要几次操作才可以将数组全部变成0。

题目链接:https://codeforces.com/problemset/problem/2049/A

题目解析

  可以看出解题目的重点是数组中0的位置,针对0的位置分为四种情况:

  • 数组全是0,返回0。
  • 数组没有0,返回1
  • 数组中0只在边缘,返回1。
  • 数组中0出现在中间,返回2。
    得出以下代码:
void mex_destruction() {
    vector<int>array;
    get_array(array);
    int number_array = array.size();
    vector<int> loc_0 = get_location(array);
    // 全是0的情况
    if(loc_0.size() == number_array){
        cout<<0<<'\n';
        return;
    }
    for(int & it : loc_0){
        // 如果中间出现0,那么就返回2(表示一定会出现2个以上的字串)
        if(it!=0 && it!=number_array-1){
            cout<<2<<"\n";
            return;
        }
    }
    cout<<"1"<<'\n';
}

vector<int> get_location(vector<int> array) {
    vector<int>location;
    for(int i=0 ;i<array.size();i++){
        if(array[i] == 0){
            location.push_back(i);
        }
    }
    return location;
}

不过居然出错了,经过分析,发现有一种恶心的情况:

1
4
0 0 1 2

在该种情况下,程序判定第二个0在中间,但是本质上还是在边缘,为了处理这种情况,需要添加边缘0的唯一化[2]

std::vector<int> removeEdgeZeros(const std::vector<int> arr) {
    int n = arr.size();
    int start = 0;
    int end = n - 1;
    while (start < n && arr[start] == 0) {
        start++;
    }
    while (end >= 0 && arr[end] == 0) {
        end--;
    }
    if (start > end) {
        return {};
    }
    return vector<int>(arr.begin() + start, arr.begin() + end + 1);
}

完美收官。可以看到性能还是不错的。算法的时间复杂度也控制在O(n),主要的时间消耗是在边缘0的唯一化和找出全部0的位置。

完整代码

//
// Created by FreeMan on 25-1-7.
//

#include<bits/stdc++.h>

void mex_destruction();

void get_array(std::vector<int>& array);

std::vector<int> removeEdgeZeros(const std::vector<int> arr);

std::vector<int> get_location(std::vector<int> array);

using namespace std;

int main(){
    int number;
    cin>>number;
    while (number>0){
        mex_destruction();
        number--;
    }
}

void mex_destruction() {
    vector<int>array;
    get_array(array);
    int number_array = array.size();
    vector<int> loc_0 = get_location(array);
    // 全是0的情况
    if(loc_0.size() == number_array){
        cout<<0<<'\n';
        return;
    }
    for(int & it : loc_0){
        // 如果中间出现0,那么就返回2(表示一定会出现2个以上的字串)
        if(it!=0 && it!=number_array-1){
            cout<<2<<"\n";
            return;
        }
    }
    cout<<"1"<<'\n';
}

vector<int> get_location(vector<int> array) {
    vector<int>location;
    for(int i=0 ;i<array.size();i++){
        if(array[i] == 0){
            location.push_back(i);
        }
    }
    return location;
}

void get_array(vector<int> & array) {
    int number_array;
    cin>>number_array;
    while(number_array>0){
        int temp_number;
        cin>>temp_number;
        array.push_back(temp_number);
        number_array--;
    }
    array = removeEdgeZeros(array);
}

std::vector<int> removeEdgeZeros(const std::vector<int> arr) {
    int n = arr.size();
    int start = 0;
    int end = n - 1;
    while (start < n && arr[start] == 0) {
        start++;
    }
    while (end >= 0 && arr[end] == 0) {
        end--;
    }
    if (start > end) {
        return {};
    }
    return vector<int>(arr.begin() + start, arr.begin() + end + 1);
}

反思

  其实有一种新的思考方式:找被0包裹的字串数。可以参考篇文章: https://blog.csdn.net/qq_68286180/article/details/144634211


  1. MEX(The Minist Extensive)指的是一个数组之外的最小的非负的数。因此对于一个含有0或负数的数组,使用MEX失效 ↩︎

  2. 其实就是把边缘出现多个0变成一个0。 ↩︎

标签:arr,int,number,start,vector,array,MEX,Destruction
From: https://www.cnblogs.com/freeman271828/p/18657292

相关文章

  • MEX Game 2 (Hard Version)
    [CF1943E2]MEXGame2下文中称\(\text{Alice}\)为\(L\),\(\text{Bob}\)为\(Q\)。题意有\(n\)个数,记作\(a_1,a_2,\ldots,a_n\),开始有一个空集\(b\)。每次\(L\)从\(a\)中取出一个数\(x\),将\(x\)放入集合\(b\),并将其从\(a\)中删除。\(Q\)从\(a\)中删除最多......
  • P10370 「LAOI-4」Mex Tower (Hard ver.) 题解
    有一定难度的思维题。题目传送门思路首先,\(\operatorname{mex}(x,y)\)的结果一定为\(0,1,2\),因为只有两个数,所以结果最多为\(2\)(\(x=1,y=0\)或\(x=0,y=1\)时)。因此,可以将问题转化为最后的数是否为\(2\)。考虑倒推,当\(n=1\)时,显然只能为\(2\);要从\(n=2\)的情况变为......
  • MEXimize the Score
    算法首先观察对于一个确定的数组\(x\),怎么去计算这样的答案对于每一个值\(u\),假设其出现次数为\(Ap_u\),那么最多产生的贡献就为\(\displaystyle\min_{v\lequ}Ap_v\),原因是显而易见的那么怎么对于每一个子串串都计算答案呢,我们考虑串串之间的共同点,对于......
  • CF2050G Tree Destruction 题解
    【题意简述】你有一棵树,你可以从里面删除一条链上的节点,问剩下的点的联通块数量最大是多少。【思路】一眼树形dp,默认根为\(1\)。我们以这棵树的\(1\)节点作为示例。设\(dp[i][0]\)表示\(i\)节点的子树中选一条链,\(i\)​不在链上的最大联通块数。设\(dp[i][1]\)......
  • P5631 最小mex生成树
    P5631最小mex生成树题目背景这是一道经典题。题目描述给定\(n\)个点\(m\)条边的无向连通图,边有边权。设一个自然数集合\(S\)的\(\text{mex}\)为:最小的、没有出现在\(S\)中的自然数。现在你要求出一个这个图的生成树,使得其边权集合的\(\text{mex}\)尽可能小。......
  • AI绘画 Stable Diffusion 【真人模型】:一款适合画中国女孩的国产真人大模型MexxL_LCM2
    目前StableDiffusion大模型中,真人模型可谓,百发齐放,精彩纷呈,令人目眩神迷。真人模型充分展现着栩栩如生的美态与神采。逼真的面部表情、流畅自然的动作,融合了真实和[虚拟的]完美之美。然而很多真人大模型都是参照着西方女性的特征,在绘制中国女性方面,还略微逊色。今天就和大......
  • 【双堆懒删除】codeforces 1294 D. MEX maximizing
    前言双堆懒删除当需要维护若干元素中的最大值(或最小值)时,可以用一个堆维护,但是堆只擅长处理堆顶元素,对堆中任意元素的处理就束手无策了。此时,可以引入另外一个堆,我们定义原来的堆为保存堆\(ex\),新的堆为懒删除堆\(de\)。那么当需要从保存堆中删除任意一个元素时,可以先将元素放......
  • 题解:P10370 「LAOI-4」Mex Tower (Hard ver.)
    ProblemLink「LAOI-4」MexTower(Hardver.)题意给定一个长度为$n$的序列$a$,求序列的$\operatorname{Mex}$值是否大于等于其他所有长度为$n$的自然数序列的$\operatorname{Mex}$值。Solution不难发现,两个数或一个序列的$\operatorname{Mex}$一定是......
  • 苯乙酰谷氨酰胺-d5 是氘标记的苯乙酰谷氨酰胺 |MedChemExpress (MCE)
    品牌:MedChemExpress(MCE)CAS:1331909-01-3纯度:98.01%分子式:C₁₃H₁₁D₅N₂O₄分子量:269.31存储条件:粉末:-20°C,3年;4°C,2年。溶剂中:-80°C,6个月;-20°C,1个月。运输条件:美国大陆的室温;其他地区可能有所不同。产品活性:Phenylacetylglutamine-d5是Phenylacetylglutamine(......
  • Pifithrin-α hydrobromide 是一种 p53 抑制剂 |MedChemExpress (MCE)
    CAS:63208-82-2品牌:MedChemExpress(MCE)存储条件:4°C,sealedstorage,awayfrommoisture生物活性:Pifithrin-αhydrobromide是一种 p53 抑制剂,可阻断其转录活性并防止细胞凋亡。Pifithrin-αhydrobromide也是一种 arylhydrocarbonreceptor(AhR) 激动剂。IC5......