Problem - D - Codeforces
给定一个由n个整数组成的初始数组a,位置从1到n编号。
对该数组执行q次查询,每次查询选择一个区间[li, ri](1≤li≤ri≤n),并将该区间内所有元素的值都改为i。查询的顺序不能更改,并且必须应用所有q次查询。已知每个位置从1到n都至少被一个区间覆盖。
我们可能会提供一个问题,即检查某个给定的数组(由n个取值范围为1到q的整数组成)是否可以通过上述查询获得。但是,我们决定这太容易了。
因此,我们对其进行了增强。在此数组中选择一些位置(可能为空),并将这些位置上的元素值设置为0。
你的任务是检查是否可以通过上述查询获得该数组。如果可以获取,则还需要恢复该数组。
如果有多个可能的数组,则打印其中任何一个。 输入格式 第一行包含两个整数n和q(1≤n,q≤2⋅105)——数组元素数量和对其执行的查询数量。
第二行包含n个整数a1,a2,…,an(0≤ai≤q)——结果数组。如果某个位置j处的元素等于0,则该位置的元素值可以是1到q之间的任意整数。 输出格式 如果可以通过q次查询获得数组a,则输出“YES”。对于每个查询,都会单独选择区间[li, ri]。必须覆盖1到n中的每个位置。
否则输出“NO”。
如果可以获得某个数组,则在第二行上打印n个整数——第i个数字应该等于结果数组的第i个元素,并且应具有1到q的值。该数组应恰好通过执行q次查询获得。
如果有多个可能的数组,则打印其中任何一个。
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
题解:
通过我们观察样例我们发现,如果不包含0的数组满足条件,那么让0等于左右相邻位置不等于0的,这个数组依旧可以构造出来
不满足的条件1是在两个相同值之间,有一个比他们小的数,按照从小到大的涂改顺序这样肯定不行
其二,数组中没有出现q,q是一定要出现的,因为他是最后一次修改,不会被其他值覆盖
那么我们只要在符合条件的,数组中找到一个0,修改为q即可
注意最后让所有0等于左右相邻,不为0的
st查询复杂度只有O(1),比线段树快很多,虽然不能修改,但出现多次查询的问题是,十分有用
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
typedef unsigned long long ULL;
const int N = 3e5 + 10;
int mod = 1e9 + 7;
int n,q;
int a[N];
int f[N][30];
vector<int> p[N];
void st()
{
for(int j = 1;(1 << j) <= n;j++)
{
for(int i = 1;i + (1 << j) - 1 <= n;i++)
{
f[i][j] = min(f[i][j - 1],f[i + (1 << (j - 1))][j - 1]);
}
}
}
int query(int l,int r)
{
int k = log2(r - l + 1);
return min(f[l][k],f[r - (1 << k) + 1][k]);
}
void solve()
{
cin >> n >> q;
memset(f,0x3f,sizeof f);
for(int i = 1;i <= n;i++)
{
cin >> a[i];
if(a[i])
f[i][0] = a[i];
p[a[i]].push_back(i);
}
st();
for(int i = 1;i <= q;i++)
{
int now = p[i].size();
if(now >= 2)
{
int l = p[i][0];
int r = p[i].back();
int w = query(l,r);
if(w < i)
{
cout <<"NO";
return ;
}
}
}
if(!p[q].size())
{
int f = 0;
for(int i = 1;i <= n;i++)
{
if(a[i] == 0)
{
a[i] = q;
f = 1;
break;
}
}
if(!f)
{
cout <<"NO";
return ;
}
}
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];
}
cout <<"YES\n";
for(int i = 1;i <= n;i++)
cout << a[i] <<" ";
}
signed main()
{
ios::sync_with_stdio(0 );
cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}