codeforces 1023D Array Restoration

考场上东拼西凑打补丁才做出来,多次找到hack自己的数据,WA ON pretest6 5发,然后想到最后一个数字必须出现,被之前的数字覆盖也要出现,才A掉。首先想到对于每个出现的数字,记录一蛤这个数字最左边出现的地方L[i]和最右边出现的地方R[i],说明在第i次query的区间至少要包括L[i]到R[i]这段区间,那么我们直接模拟一蛤区间覆盖,看一蛤最后的情况a数组和目标数组to的关系如何。接下来就是对0的处理,WA了好久,考虑到每个询问必须选出区间,如果q没有出现是不行的,必须要找一个位置放q,这种情况判断一下,其他没出现的就无所谓了,可以直接被q给覆盖掉,还有就是最后a数组中如果还有0的地方,那么可以由附近的不是0的数的区间拓展过来,那么正着扫一遍,倒着到一遍就好了。比赛的时候直接拿出线段树的板子搞了一蛤,后面又写了一遍ST表覆盖版本

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<cmath>
#define maxl 200010
#define inf 20000000001

using namespace std;

int n,q;
int L[maxl],R[maxl],to[maxl],a[maxl],f[19][maxl];
long long ans[maxl];
bool flag;

inline void prework()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=q;i++)
		L[i]=n+1,R[i]=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&to[i]);
		if(to[i]>0)
		{
			L[to[i]]=min(i,L[to[i]]);
			R[to[i]]=max(i,R[to[i]]);
		}
	}
}

inline void mainwork()
{
	flag=true;
	for(int i=1;i<=q;i++)
	{
		if(L[i]<=R[i])
		{
			int l=log2(R[i]-L[i]+1);
			f[l][L[i]]=i;f[l][R[i]-(1<<l)+1]=i;
		}
	}
	for(int l=18;l>=1;l--)
		for(int i=1;i<=n;i++)
		if(f[l][i])
		{
			f[l-1][i]=max(f[l][i],f[l-1][i]);
			f[l-1][i+(1<<(l-1))]=max(f[l-1][i+(1<<(l-1))],f[l][i]);
		}
	for(int i=1;i<=n;i++)
		a[i]=f[0][i];
	for(int i=1;i<=n;i++)
	if(to[i]>0 && a[i]!=to[i])
	{
		flag=false;
		return;
	}
	else
		ans[i]=a[i];
	int num=0;
	for(int i=1;i<=n && L[q]>n;i++)
	if(to[i]==0)
	{
		ans[i]=q;L[q]=i;
		break;
	}
	if(L[q]>n)
	{
		flag=false;
		return;
	}
	for(int i=1;i<=n;i++)
	if(ans[i]==0)
	{
		num=max(ans[i-1],ans[i+1]);
		if(num!=0)
			ans[i]=num;
	}
	for(int i=n;i>=1;i--)
	if(ans[i]==0)
	{
		num=max(ans[i-1],ans[i+1]);
		if(num!=0)
			ans[i]=num;
	}
	
}

inline void print()
{
	if(flag)
	{
		printf("YES\n");
		for(int i=1;i<=n;i++)
			printf("%d ",ans[i]);
	}
	else
		printf("NO");
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#define maxl 200010
#define inf 20000000001

using namespace std;

int n,q;
int L[maxl],R[maxl],to[maxl],a[maxl];
struct node
{
	int l,r;
	long long sum,tag;
}tree[maxl<<2];
long long ans[maxl];
bool flag;

inline void build(int k,int l,int r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].tag=inf;
	if(l==r)
	{
		tree[k].sum=0;
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);build(k<<1|1,mid+1,r);
	tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}

inline void gank(int k)
{
	int v;
	if(tree[k].l==tree[k].r)
		return;
	if(tree[k].tag!=inf)
	{
		v=tree[k].tag;
		tree[k<<1].sum=1ll*(tree[k<<1].r-tree[k<<1].l+1)*v;
		tree[k<<1|1].sum=1ll*(tree[k<<1|1].r-tree[k<<1|1].l+1)*v;
		tree[k<<1].tag=v;tree[k<<1|1].tag=v;
		tree[k].tag=inf;
	}
}

inline void add(int k,int l,int r,int v)
{
	if(tree[k].tag!=inf)
		gank(k);
	if(tree[k].l==l && tree[k].r==r)
	{
		tree[k].sum=1ll*(r-l+1)*v;
		tree[k].tag=v;
		return;
	}
	int mid=(tree[k].l+tree[k].r)>>1;
	if(r<=mid)
		add(k<<1,l,r,v);
	else
	if(l>mid)
		add(k<<1|1,l,r,v);
	else
		add(k<<1,l,mid,v),add(k<<1|1,mid+1,r,v);
	tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}

inline void prework()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=q;i++)
		L[i]=n+1,R[i]=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&to[i]);
		if(to[i]>0)
		{
			L[to[i]]=min(i,L[to[i]]);
			R[to[i]]=max(i,R[to[i]]);
		}
	}
	build(1,1,n);
}

inline void get(int k)
{
	if(tree[k].tag!=inf)
		gank(k);
	if(tree[k].l==tree[k].r)
	{
		a[tree[k].l]=tree[k].sum;
		return;
	}
	int mid=(tree[k].l+tree[k].r)>>1;
	get(k<<1);get(k<<1|1);
}

inline void mainwork()
{
	flag=true;
	for(int i=1;i<=q;i++)
	{
		if(L[i]<=R[i])
			add(1,L[i],R[i],i);
	}
	get(1);	
	for(int i=1;i<=n;i++)
	if(to[i]>0 && a[i]!=to[i])
	{
		flag=false;
		return;
	}
	else
		ans[i]=a[i];
	int num=0;
	for(int i=1;i<=n && L[q]>n;i++)
	if(to[i]==0)
	{
		ans[i]=q;L[q]=i;
		break;
	}
	if(L[q]>n)
	{
		flag=false;
		return;
	}
	for(int i=1;i<=n;i++)
	if(ans[i]==0)
	{
		num=max(ans[i-1],ans[i+1]);
		if(num!=0)
			ans[i]=num;
	}
	for(int i=n;i>=1;i--)
	if(ans[i]==0)
	{
		num=max(ans[i-1],ans[i+1]);
		if(num!=0)
			ans[i]=num;
	}
	
}

inline void print()
{
	if(flag)
	{
		printf("YES\n");
		for(int i=1;i<=n;i++)
			printf("%d ",ans[i]);
	}
	else
		printf("NO");
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值