CF1759G 题解

洛谷传送门 & CF 传送门

思路

这题中 bi=max(p2i,p2i+1)b_i=\max(p_{2i},p_{2i+1})(如果 ii00 开始),而题目又要求 pp 的字典序最小,则我们可以让每个 p2i+1=bip_{2i+1}=b_i,而让 p2i<bip_{2i}<b_i。这题的贪心时可以倒着枚举,每次选当前最大的且没被选过的 <bi<b_i 的元素作为 p2ip_{2i},再把这个数删了。这一点可以用 STL 中的 vector + lower_bound + erase(当然你用 set + lowerbound + erase 也可以)。记住还要时刻判断是否合法。

代码

# include <bits/stdc++.h>
using namespace std;
int t, n, m, a[200005], b[200005];
bool vis[200005];
vector <int> v;
vector <int> :: iterator j;
void f () {
	cin >> n;
	m = n >> 1;
	v.clear (); //多组数据要清空
	for (int i = 1; i <= n; ++ i)
		vis[i] = 0;
	for (int i = 0; i < m; ++ i)
		cin >> b[i];
	for (int i = 0; i < m; ++ i)
		if (b[i] < 2 || vis[b[i]]) { //是 1 或者出现过了,不合法
			cout << "-1\n";
			return ;
		} else
			vis[a[i * 2 + 1] = b[i]] = 1;
	for (int i = 1; i <= n; ++ i)
		if (! vis[i]) //没出现过
			v.push_back (i); //存入 vector
	for (int i = m - 1; ~ i; -- i) {
		j = lower_bound (v.begin (), v.end (), b[i]) - 1; //lower_bound 再 -1 就是最大的比它小的值了
		if (j < v.begin ()) { //没有比它小的数,不合法
			cout << "-1\n";
			return ;
		}
		a[i << 1] = *j; //记录
		v.erase (j); //删掉元素
	}
	for (int i = 0; i < n; ++ i)
		cout << a[i] << ' ';
	cout << '\n';
	return ;
}
int main () {
	cin >> t;
	while (t --)
		f ();
	return 0;
}
posted @ 2023-08-17 21:27  Vitamin_B  阅读(8)  评论(0)    收藏  举报  来源