类似于树状数组求前缀和,将整个值域做成树状数组,如果两个数字中间出现了较小的数字,就会发现维护的前缀和发生了改变

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=200000+10;
int a[MAXN];
int C[MAXN];
int vis[MAXN];
int n,q;
void add(int i,int x){
    for(;i<=q;i+=(i&(-i)))
    {
        C[i]+=x;
    }
}
ll sum(int x)
{
    ll sum=0;
    for(int i=x;i>=1;i-=i&(-i))
    {
        sum+=C[i];
    }
    return sum;
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
      scanf("%d",&a[i]);
    bool flag=true;
    for(int i=1;i<=n;i++)
    {
        if(a[i])
        {
            if(vis[a[i]])
            {
                if(sum(a[i])!=vis[a[i]])
                {
                    flag=false;
                    break;    
                }
                add(a[i],1);
                vis[a[i]]=sum(a[i]);
            }
            else
            {
                add(a[i],1);
                vis[a[i]]=sum(a[i]);
            }
        }
    }
    bool flag0=false,flagq=false;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==0)
           flag0=true;
        if(a[i]==q)
           flagq=true;
    }
    if(flag==false||flag0==false&&flagq==false)
    {
        printf("NO\n");
        return 0;
    }
    a[0]=1;
    bool judge=false;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==0)
        {
            if(judge==false)
            {
                judge=true;
                if(flagq==false)
                {
                    a[i]=q;
                }
                else
                    a[i]=a[i-1];
            }
            else
               a[i]=a[i-1];
        }
    }
    printf("YES\n");
    for(int i=1;i<=n;i++)
      printf("%d ",a[i]);
    printf("\n");
}