CF1759G 题解
思路
这题中 (如果 从 开始),而题目又要求 的字典序最小,则我们可以让每个 ,而让 。这题的贪心时可以倒着枚举,每次选当前最大的且没被选过的 的元素作为 ,再把这个数删了。这一点可以用 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;
}

浙公网安备 33010602011771号