类似于树状数组求前缀和,将整个值域做成树状数组,如果两个数字中间出现了较小的数字,就会发现维护的前缀和发生了改变
#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 "); 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 "); for(int i=1;i<=n;i++) printf("%d ",a[i]); printf(" "); }