Codeforces Round #767 (Div. 2) Meximum Array

本文介绍了一种算法,用于解决给定一个非负整数序列,如何通过特定规则构造出一个字典序尽可能大的新序列的问题。文章详细阐述了解决方案的思路,包括使用贪心策略和记录数字出现次数的方法。

maxium array

题意

给定一个 a 序列,当 a 非空时可以选择从 a 中切出前 k 个数字(有才行),这 k 个数字取一个最小的且不存在于该非负序列中的数字,得出来的结果加给 b 序列,要求构造出的 b 序列满足字典序尽可能大

样例:

2 2 3 4 0 1 2 0

要让字典序尽可能大,在第6位后面截一下,它之前的数字全都有,所以我们得到5,后面两位得到1.故答案是5 1

0 0 2 1 1 1 0 0 1 1

同理,返回3 2 2 0

思路:

要让字典序尽可能大,所以我们要让每一位的数字尽可能的大,且让数位尽可能多,可以贪心,同时数组应该尽可能全部用完。

标记一个cnt记录数字出现的次数,顺序遍历时,每次不断更新当前已经出现过的数,直到更新结果无法保持连续时,那么空出来的那个数字就是我们应该要填的了。

另外,如果发现某一个数字在当前是空缺却它之后不会再出现的话,那我们当然应该直接把它加入答案。把它留到后面并不会对我们有什么好处。

细节见代码;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll t;
ll n;
ll cnt[200010];//记录每个数出现的次数 
ll mas[200010];
ll vis[200010];//标记是否在当前已经被记录 
int main()
{
	cin>>t;
	while(t--){
		memset(vis,0,sizeof vis);
		memset(mas,0,sizeof vis);
		memset(cnt,0,sizeof cnt);
		cin>>n;
		ll ans[200010]; 
		for(int i=1;i<=n;++i){
			cin>>mas[i];
			cnt[mas[i]]++; 
		}
		ll bu=0;//记录需要补的数字
		ll num=0;
		for(int i=1;i<=n;++i){
			vis[mas[i]]=1;//表示当前这个数已经出现 
			while(vis[bu]) bu++;
			cnt[mas[i]]--;//此时代表再次之后mas【i】出现的次数
			if(!cnt[bu])//之后不再有这个需要补的数字,所以这里选择直接把它加入答案
			{
			    ans[++num]=bu;
				for(int k=0;k<bu;++k) vis[k]=0;
				bu=0;	
			} 
		}
		cout<<num<<endl;
		for(int i=1;i<=num;++i) cout<<ans[i]<<" ";
		cout<<endl;
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值