题意是给出一个序列,q次操作,每次是从1开始到q,每次把l到r的连续一段改成次数,然后它会将一些数字变成0,问你这个序列服不服合规范,符合输出目标序列,不符合则输出no
思路:将每个数字最左最右的位置标记,因为q一定会出现,所以特判q,然后把从左到右整一段变成当前数字,普通的操作应该会超时,所以用线段树进行区间修改,然后用线段树完成的区间与给出来的区间对比,0的话就是满足的,不是0又不相同只能输出no,然后对第一个元素的位置变为1,然后就把0修改为前一个元素就完成了
//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=200500;
int n,q,a[N],lazy[N<<3],tree[N<<3],b[N],l[N],r[N];
vector<int>vec[N];
void push_down(int pos){
int lson=pos<<1,rson=pos<<1|1;
if(lazy[pos]){
lazy[lson]=lazy[rson]=tree[lson]=tree[rson]=lazy[pos];
lazy[pos]=0;
}
}
void insert(int l,int r,int pos,int L,int R,int wei){
if(l>=L&&r<=R){
lazy[pos]=tree[pos]=wei;return;
}
push_down(pos);
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)insert(mid+1,r,rson,L,R,wei);
else if(mid>=R)insert(l,mid,lson,L,R,wei);
else insert(l,mid,lson,L,R,wei),insert(mid+1,r,rson,L,R,wei);
}
void query(int l,int r,int pos){
if(l==r){b[l]=tree[pos];return;}
push_down(pos);
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
query(l,mid,lson),query(mid+1,r,rson);
}
int main(){
int flg=0;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]==q)flg=1;
}
if(!flg){
for(int i=1;i<=n;i++)if(!a[i]){a[i]=q;flg=1;break;}
if(!flg)return puts("NO"),0;
}\\特判
for(int i=1;i<=n;i++)if(a[i]){
if(!l[a[i]])l[a[i]]=i;\\记录最左端端点
r[a[i]]=i;\\记录最右端端点
}for(int i=1;i<=q;i++)if(l[i])insert(1,n,1,l[i],r[i],i);\\线段树修改区间
query(1,n,1);
for(int i=1;i<=n;i++)if(a[i]!=b[i]&&a[i])return puts("NO"),0;
b[0]=1;
for(int i=1;i<=n;i++)if(!b[i])b[i]=b[i-1];
puts("YES");
for(int i=1;i<=n;i++)printf("%d ",b[i]);
}
//以上为借鉴别人的代码