题目链接:http://codeforces.com/problemset/problem/1023/D
题目大意:有一个长度为n的序列a,有q次操作。第i次操作可以用i覆盖一段区间内的数。序列a的每个位置至少被改一次。得到最终的序列,然后将序列里的某些位置变成0,输出一种可能的置零之前的最终序列,或无解
思路:通过分析可知,两个相同的数之间的数不可能比端点的数小(除非是零)。这个可以用线段树来维护每个区间的最小值。
还需要考虑0的情况和q的情况。因为q是必须要有的,所以若原来序列没有0,没有q,就是NO。在我们建立线段树前,把0的值置为它的前一个数。这里还要分是否有q,具体看代码。(总之情况较多,建议讨论处理,防止没有考虑全)。。。
代码:(写丑了。。。)
#include<bits/stdc++.h>
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std;
const int MAXN=2e5+10;
int Min[MAXN<<2];
int a[MAXN];
int used[MAXN];
int judge[MAXN];
void PushUP(int rt)
{
Min[rt] = min(Min[rt<<1] , Min[rt<<1|1]);
}
void build(int l,int r,int rt) {
Min[rt]=2e9;
if (l == r) {
Min[rt]=a[l];
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUP(rt);
}
void update(int p,int sc,int l,int r,int rt) {
if (l == r) {
Min[rt] = sc;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p , sc , lson);
else update(p , sc , rson);
PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
return Min[rt];
}
int m = (l + r) >> 1;
int ret = 2e9;
if (L <= m) ret = min(ret , query(L , R , lson));
if (R > m) ret = min(ret , query(L , R , rson));
return ret;
}
int main()
{
int n,q,f1,f2;
f1=f2=0;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==0)
f1=1;
if(a[i]==q)
f2=1;
}
int tem;
int flag=1;
if(f1==0)
{
if(f2==0)
flag=0;
else
{
build(1,n,1);
for(int i=1;i<=n;i++)
{
if(used[a[i]]==0)
used[a[i]]=i;
else
{
tem=query(used[a[i]],i,1,n,1);
if(tem<a[i])
{
flag=0;
break;
}
used[a[i]]=i;
}
}
}
if(flag==0)
{
printf("NO\n");
}
else
{
printf("YES\n");
printf("%d",a[1]);
for(int i=2;i<=n;i++)
printf(" %d",a[i]);
}
}
else
{
if(f2==0)
{
for(int i=1;i<=n;i++)
{
if(a[i]==0)
{
a[i]=q;
break;
}
}
}
else
{
if(a[1]==0)
a[1]=1;
}
for(int i=2;i<=n;i++)
{
if(a[i]==0)
a[i]=a[i-1];
}
build(1,n,1);
for(int i=1;i<=n;i++)
{
if(used[a[i]]==0)
used[a[i]]=i;
else
{
tem=query(used[a[i]],i,1,n,1);
if(tem<a[i])
{
flag=0;
break;
}
used[a[i]]=i;
}
}
if(flag==0)
{
printf("NO\n");
}
else
{
printf("YES\n");
printf("%d",a[1]);
for(int i=2;i<=n;i++)
printf(" %d",a[i]);
}
}
return 0;
}