CF1023D Array Restoration

不合法的情况只有两种

  1. aba,其中a>b

  2. 序列中没有0,没有m

第一种可直接无脑主席树判断,也可以和下面一样用set

考虑填数,对于 i 位置,\(a_i=0\),若 i 左右两边存在相等的数,设为w,i 位置填\(\max(w)\),否则置为 1

这种填数方案保证当前位置合法,并且不会对其他位置造成新的影响

维护这个\(\max(w)\),可以在w第一次出现时加入set,最后一次出现时删掉,每次取\(* rbegin()\)即可

#include<set>
#include<cstdio>
#include<iostream>
using namespace std;
const int N=2e5+11;
struct tree{
	int lc,rc;
	int sum;
}tre[20*N];
int tot=1;
int n,q;
int a[N];
int l[N],r[N];
int root[N];
set<int> st;
inline int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0') ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;
}
inline int min_(int x,int y){return x>y?y:x;}
inline int max_(int x,int y){return x>y?x:y;}
void insert(int &i,int j,int l,int r,int x)
{
	if(!i) i=++tot;
	tre[i].lc=tre[j].lc;
	tre[i].rc=tre[j].rc;
	tre[i].sum=tre[j].sum+1;
	if(l==r) return;
	int mid=(l+r)>>1;
	if(x<=mid) insert(tre[i].lc=0,tre[j].lc,l,mid,x);
	else insert(tre[i].rc=0,tre[j].rc,mid+1,r,x);
	return;
}
int query(int i,int j,int l,int r,int L,int R)
{
	if(l>=L&&r<=R) return tre[j].sum-tre[i].sum;
	int mid=(l+r)>>1;
	int ans=0;
	if(L<=mid) ans=query(tre[i].lc,tre[j].lc,l,mid,L,R);
	if(R>mid) ans+=query(tre[i].rc,tre[j].rc,mid+1,r,L,R);
	return ans;
}
int main()
{
	n=read();
	q=read();
	for(int i=1;i<=n;++i) a[i]=read();
	root[0]=1;
	int maxx=0,sum=0;
	for(int i=1;i<=n;++i)
	{
		if(a[i]==0){++sum;root[i]=root[i-1];continue;}
		insert(root[i],root[i-1],1,q,a[i]);
		if(!l[a[i]]) l[a[i]]=r[a[i]]=i;
		else r[a[i]]=i;
		maxx=max_(maxx,a[i]);
	}
	if(sum==0&&maxx!=q){printf("%s\n","NO");return 0;}
	for(int i=2;i<=maxx;++i)
	{
		if(l[i]==0) continue;
		if(query(root[l[i]-1],root[r[i]],1,q,1,i-1)){printf("%s\n","NO");return 0;}
	}
	bool jd=0;
	if(maxx!=q) jd=1;
	for(int i=1;i<=n;++i)
	{
		if(jd){if(a[i]==0){a[i]=q;jd=0;continue;}}
		if(a[i]==0){if(st.size()) a[i]=*st.rbegin();else a[i]=1;}
		else{if(l[a[i]]==r[a[i]])continue;if(i==l[a[i]])st.insert(a[i]);else if(i==r[a[i]])st.erase(st.find(a[i]));}
	}
	cout<<"YES"<<endl;
	for(int i=1;i<=n;++i) printf("%d ",a[i]);
	return 0;
}
posted @ 2021-11-03 21:42  sitiy  阅读(28)  评论(0编辑  收藏  举报