感觉是很有意思的一道题呢~
开 始 我 想 的 是 一 种 数 字 最 多 出 现 连 续 的 一 段 开始我想的是一种数字最多出现连续的一段 开始我想的是一种数字最多出现连续的一段
但 是 如 果 后 面 的 区 间 覆 盖 在 前 面 区 间 的 中 间 呢 ? 但是如果后面的区间覆盖在前面区间的中间呢? 但是如果后面的区间覆盖在前面区间的中间呢?
那 么 一 种 数 字 就 分 成 了 多 段 . . . . . . . 那么一种数字就分成了多段....... 那么一种数字就分成了多段.......
但 在 这 样 的 考 虑 当 中 , 不 合 法 的 情 况 也 浮 出 水 面 . . . . . 但在这样的考虑当中,不合法的情况也浮出水面..... 但在这样的考虑当中,不合法的情况也浮出水面.....
Ⅰ . 数 字 x 出 现 的 最 左 端 是 l , 最 右 端 是 r , 那 么 [ l , r ] 不 能 比 x 小 \color{Red}Ⅰ.数字x出现的最左端是l,最右端是r,那么[l,r]不能比x小 Ⅰ.数字x出现的最左端是l,最右端是r,那么[l,r]不能比x小
Ⅱ . 数 字 q 一 定 出 现 , 因 为 是 最 后 一 次 染 色 , 不 会 被 别 人 覆 盖 \color{Red}Ⅱ.数字q一定出现,因为是最后一次染色,不会被别人覆盖 Ⅱ.数字q一定出现,因为是最后一次染色,不会被别人覆盖
如 果 既 没 有 数 字 q , 也 没 有 数 字 0 能 填 充 q , 那 么 也 不 合 法 如果既没有数字q,也没有数字0能填充q,那么也不合法 如果既没有数字q,也没有数字0能填充q,那么也不合法
如 果 上 面 都 满 足 条 件 , 那 么 把 所 有 的 0 填 充 为 附 近 的 数 即 可 如果上面都满足条件,那么把所有的0填充为附近的数即可 如果上面都满足条件,那么把所有的0填充为附近的数即可
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,q,a[maxn],ans[maxn][21];
vector<int>vec[maxn];
void over(){
cout<<"NO";exit(0);
}
int query(int l,int r){
int k=log2(r-l+1);
return min(ans[l][k],ans[r-(1<<k)+1][k]);
}
void Make_St()
{
for(int j=1;j<=21;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
ans[i][j]=min(ans[i][j-1],ans[i+(1<<(j-1))][j-1]);
}
int main()
{
cin>>n>>q;
memset(ans,20,sizeof(ans));
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]!=0) ans[i][0]=a[i];
}
Make_St();
for(int i=1;i<=n;i++)
{
if(a[i]==0) continue;
else if(a[i]==a[i-1]) continue;
else vec[a[i]].push_back(i);
}
for(int i=1;i<=q;i++)
{
int top=vec[i].size();
if(top>=2)
{
int l=vec[i][0],r=vec[i][top-1];
if(query(l,r)<i) over();
}
}
if(vec[q].size()==0)//最后一个数一定存在
{
int flag=0;
for(int i=1;i<=n;i++)
if(a[i]==0)
{
flag=1,a[i]=q;
break;
}
if(!flag) over();
}
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"<<endl;
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
}
树状数组版本
树 状 数 组 怎 么 做 ? ? 树状数组怎么做?? 树状数组怎么做??
设 x 数 出 现 在 l 位 置 和 r 位 置 设x数出现在l位置和r位置 设x数出现在l位置和r位置
那 么 要 求 l 到 r 间 没 有 比 x 小 的 数 , 也 就 是 l 位 置 前 小 于 x 的 数 那么要求l到r间没有比x小的数,也就是l位置前小于x的数 那么要求l到r间没有比x小的数,也就是l位置前小于x的数
等 于 r 位 置 之 前 小 于 x 的 数 等于r位置之前小于x的数 等于r位置之前小于x的数
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,q,a[maxn],vis[maxn];
void over(){
cout<<"NO";exit(0);
}
class Binary_Search_Tree
{
private:
int sumn[maxn];
int lowbit(int x){ return x&(-x); }
public:
void add(int x){
for(;x<=q;x+=lowbit(x)) sumn[x]++;
}
int ask(int x){
int ans=0;
for(;x;x-=lowbit(x)) ans+=sumn[x];
return ans;
}
}bit;
int main()
{
cin>>n>>q;
int ff=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
if(a[i]==0) continue;
if(vis[a[i]]) if(bit.ask(a[i])!=vis[a[i]]) over();
bit.add(a[i]);
vis[a[i]]=bit.ask(a[i]);
if(a[i]==q) ff=1;
}
if(ff==0)//最后一个数一定存在
{
int flag=0;
for(int i=1;i<=n;i++)
if(a[i]==0)
{
flag=1,a[i]=q;
break;
}
if(!flag) over();
}
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"<<endl;
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
}