神秘代码:难度可能会稍有提升,提前适应多校
C:https://codeforces.ml/problemset/problem/1023/D
题意:给你一个长度为n的数组,然后进行q次操作,对于第i次操作,可以把任意一个区间里的所有数变成i,现在你知道这个数组里面的所有数,但里面可能有一些0,0就是不确定这个位置的数是多少的意思,问你这个数组是否合法,不合法输出NO,合法输出YES和该数组(也许有很多合法的,任意输出一个就好)。
思路:看样列会发现不合法的情况有且只有两种,第一,是两个相等的数之间夹了一个比这个小的数,这样就不合法。第二,就是一个不含零数组里面也不含q(最后一次必然会带来q)
那么对于第一种情况,我们可以用线段树(网上复制的)去维护一个区间里面的最小值,这样就可以很好的降低复杂度了。
至此,代码也就写出来了。

//author CN.TTDragon
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=2e5+7;
const double pi=acos(-1);
using namespace std;
int a[maxn],r[maxn]={0};
int seg[maxn<<2];//树 
#define lrt rt << 1
#define rrt rt << 1 | 1
void pushup(int rt) 
{
      seg[rt] = min(seg[lrt], seg[rrt]);
}
void build(int l, int r, int rt) 
{
      if(l == r) 
    {
        seg[rt] = a[l];
        return;
      }
    int m = (l + r) >> 1;
    build(l,m,lrt);//左 
    build(m+1,r,rrt);//右 
    pushup(rt);//这个就是表示父节点是儿子节点的最小值 
}
int query(int L, int R, int l, int r, int rt) 
{
      if(L <= l && r <= R) //这里的意思是,收缩到这个区间里面的时候 
    {
        return seg[rt];
      }
    int m = (l + r) >> 1;
    int ret = 0x7f7f7f7f;
    if(m >= L) 
        ret = min(ret, query(L, R, l, m, lrt));
    if(m < R) 
        ret = min(ret, query(L, R, m+1, r, rrt));
    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    int n,q;
    cin>>n>>q;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        r[a[i]]=i;//维护每个数最后一次出现 
    }
    if(r[q]==0)//最大的q没有出现过
    {
        if(r[0]==0)//同时还没有0
        {
            cout<<"NO"<<endl;
            return 0;
        }
        else
        {
            a[r[0]]=q;
            r[q]=r[0];
        }
    } 
    //把0 填了,这两个循环必然能搞定所有的0 
    for(int i=1;i<=n;i++)
    {
        if(a[i]==0)
        {
            a[i]=a[i-1];    
        }    
    } 
    for(int i=n;i>=1;i--)
    {
        if(a[i]==0)
        {
            a[i]=a[i+1];    
        }    
    } 

    //接下来就是处理不合法的过程了 

    bool ok = 1;
    build(1, n, 1);//建树去 ,看懂了 
    for(int i = 1; i <= n; i++) 
    {
          int tmp;
          if(!r[a[i]]) //这什么意思  ,先忽略 
            continue;
        //这个数出现过 
          tmp = query(i, r[a[i]], 1, n, 1);//查询最小值 
          if(tmp < a[i]) //比当前值小,不合法 
        {
            ok = 0;
            break;
          }
    }
    if(ok) 
    {
        cout<<"YES"<<endl;
          for(int i = 1; i <= n; i++) 
        {
            cout<<a[i]<<" ";
          }
          cout<<endl;
    }
    else 
    {
        cout<<"NO"<<endl;
    }
     return 0;
}

写在最后:感觉明天就会因为太菜被gg们踢出群了。