Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) D. Array Restoration

D. Array Restoration
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Initially there was an array aa consisting of nn integers. Positions in it are numbered from 11 to nn.

Exactly qq queries were performed on the array. During the ii-th query some segment (li,ri)(li,ri) (1lirin)(1≤li≤ri≤n) was selected and values of elements on positions from lili to riri inclusive got changed to ii. The order of the queries couldn't be changed and all qq queries were applied. It is also known that every position from 11 to nn got covered by at least one segment.

We could have offered you the problem about checking if some given array (consisting of nn integers with values from 11 to qq) can be obtained by the aforementioned queries. However, we decided that it will come too easy for you.

So the enhancement we introduced to it is the following. Some set of positions (possibly empty) in this array is selected and values of elements on these positions are set to 00.

Your task is to check if this array can be obtained by the aforementioned queries. Also if it can be obtained then restore this array.

If there are multiple possible arrays then print any of them.

Input

The first line contains two integers nn and qq (1n,q21051≤n,q≤2⋅105) — the number of elements of the array and the number of queries perfomed on it.

The second line contains nn integer numbers a1,a2,,ana1,a2,…,an (0aiq0≤ai≤q) — the resulting array. If element at some position jj is equal to 00then the value of element at this position can be any integer from 11 to qq.

Output

Print "YES" if the array aa can be obtained by performing qq queries. Segments (li,ri)(li,ri) (1lirin)(1≤li≤ri≤n) are chosen separately for each query. Every position from 11 to nn should be covered by at least one segment.

Otherwise print "NO".

If some array can be obtained then print nn integers on the second line — the ii-th number should be equal to the ii-th element of the resulting array and should have value from 11 to qq. This array should be obtainable by performing exactly qq queries.

If there are multiple possible arrays then print any of them.

Examples
input
Copy
4 3
1 0 2 3
output
Copy
YES
1 2 2 3
input
Copy
3 10
10 10 10
output
Copy
YES
10 10 10
input
Copy
5 6
6 5 6 2 2
output
Copy
NO
input
Copy
3 5
0 0 0
output
Copy
YES
5 4 2
Note

In the first example you can also replace 00 with 11 but not with 33.

In the second example it doesn't really matter what segments to choose until query 1010 when the segment is (1,3)(1,3).

The third example showcases the fact that the order of queries can't be changed, you can't firstly set (1,3)(1,3) to 66 and after that change (2,2)(2,2) to 55. The segment of 55 should be applied before segment of 66.

There is a lot of correct resulting arrays for the fourth example.

题意:起初我们有一个n个数的排列,然后我们随机让一些数变成了0,这些数的范围都是1-q,然后让我们求原来这个排列,他的排列求来的方法是染色,它总共有i次染色,每次

染色一个区间,让这个区间的数都变成i

 

思路:我们第i次染色会让这个区间的数都变成i,然后我们仔细想想,相同的数是连续的,如果不是连续的,肯定是后面再次在他们中间染了色,所以有规律

两个相同 的数中间肯定都是比它大的数不然就是错的,然后我们可以判断这一段的区间最小值是不是等于它就好,用线段树维护区间最小值,然后我们再来解决0的问题

因为他是随机让一些数变成的0,所以我们可以让0变成1-q中间的任意一个数,很容易发现,我们把0变成两边的一个数就行,就不要在意相同数区间有比他小的数

我们还要注意,因为我们是按顺序染色,所以最后我们肯定有一个数q,最后一次染色留下来的,如果没有这个数,我们要把其中一个0变成q,如果也没有那就直接判断错

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct sss
{
    int left;
    int right;
    int mn;
}a[200001*4];
int n,m;
int c[200001];
int f[200001];
void build(int cnt,int left,int right)
{
    a[cnt].left=left;
    a[cnt].right=right;
    if(left==right)
    {
        a[cnt].mn=c[left];
        return;
    }
    int mid=(left+right)/2;
    build(cnt*2,left,mid);
    build(cnt*2+1,mid+1,right);
    a[cnt].mn=min(a[cnt*2].mn,a[cnt*2+1].mn);
}
int updata(int cnt,int left,int right)
{
    if(left<=a[cnt].left&&right>=a[cnt].right)
    {
        return a[cnt].mn;
    }
    int mid=(a[cnt].left+a[cnt].right)/2;
    if(mid>=right) return updata(cnt*2,left,right);
    else if(left>mid) return updata(cnt*2+1,left,right);
    else{
        return min(updata(cnt*2,left,mid),updata(cnt*2+1,mid+1,right));
    } 
}
int main()
{
    scanf("%d%d",&n,&m);
    int flag1=0,flag2=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&c[i]);
        if(c[i]==m) flag1=1;
        if(c[i]==0) flag2=1;
    }
    if(flag1==0&&flag2==0)
    {
        printf("NO");
        return 0;
    }
    if(flag1==0)
    {
        for(int i=1;i<=n;i++)
        {
            if(c[i]==0)
            {
                c[i]=m;
                break;
            }
        }
    }
    int ans=1;
    for(int i=1;i<=n;i++)
    {
        if(c[i]==0) c[i]=ans;
        else ans=c[i];
    }
    build(1,1,n);
    for(int i=1;i<=n;i++)
    {
        if(f[c[i]]==0) f[c[i]]=i;
        else{
            if(updata(1,f[c[i]],i)==c[i])
            {
                f[c[i]]=i;
                 continue;
            }
            printf("NO");
            return 0;
        }
    }
    printf("YES
");
    for(int i=1;i<=n;i++)
    {
        if(i==1) printf("%d",c[i]);
        else printf(" %d",c[i]);
    }
}
原文地址:https://www.cnblogs.com/Lis-/p/9496676.html