D. Neutral Tonality
D. Neutral Tonality
You are given an array consisting of integers, as well as an array consisting of integers.
Let denote the length of the longest increasing subsequence of array . For example, = , = , = .
You need to insert the numbers into the array , at any positions, in any order. Let the resulting array be . You need to choose the positions for insertion in order to minimize .
Formally, you need to find an array that simultaneously satisfies the following conditions:
- The array is a subsequence of the array .
- The array consists of the numbers , possibly rearranged.
- The value of is the minimum possible among all suitable arrays .
Input
Each test contains multiple test cases. The first line contains a single integer — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers — the length of array and the length of array .
The second line of each test case contains integers — the elements of the array .
The third line of each test case contains integers — the elements of the array .
It is guaranteed that the sum of over all test cases does not exceed , and the sum of over all test cases does not exceed .
Output
For each test case, output numbers — the elements of the final array , obtained after the insertion, such that the value of is minimized. If there are several answers, you can output any of them.
Example
Input
7
2 1
6 4
5
5 5
1 7 2 4 5
5 4 1 2 7
1 9
7
1 2 3 4 5 6 7 8 9
3 2
1 3 5
2 4
10 5
1 9 2 3 8 1 4 7 2 9
7 8 5 4 6
2 1
2 2
1
6 1
1 1 1 1 1 1
777
Output
6 5 4
1 1 7 7 2 2 4 4 5 5
9 8 7 7 6 5 4 3 2 1
1 3 5 2 4
1 9 2 3 8 8 1 4 4 7 7 2 9 6 5
2 2 1
777 1 1 1 1 1 1
Note
In the first test case, . We can insert the number between and , then .
In the second test case, = . After the insertion, . It is easy to see that . It can be shown that it is impossible to achieve less than .
解题思路
比赛的时候猜对了做法,现在补个证明。
由于序列 中的元素在 中的相对顺序不变,因此必然必然有 。另外对序列 降序排序依次插到 中,并保持序列 的元素在 中从左到右递降的相对顺序。那么就会有 ,这是因为 的任意上升子序列中最多只会含有 中的一个元素。
下面给出使得 的构造方案,由于 的最长上升子序列取决于 ,因此关键是在插入 中的元素时不让 变大即可。
当插入的元素 ,那么直接将 插入到 的末尾即可。 必然不会出现在长度至少为 的上升子序列中,因此必然不会导致 变大。
否则找到满足 的最小的下标 ,并将 插在 之前。那么在最长上升子序列中 和 最多只会含有一个,而如果该最长上升子序列含有 ,那么将 替换成 仍然是最长上升子序列,且该最长上升子序列不再含有 中的元素(参考上面提到的 中最多含有 的一个元素),因此 不会增加。之所以要在最小的下标前插入,是为了保证 在 中降序的相对顺序。当 中较大的元素 插入到 中后,那么之后较小的元素 不可能再插到 的前面,若插入 后 后面不存在比 小的元素,而前面存在比 小的元素(即 不是插在最小的下标前面),那么 的最长上升子序列必然会选择 ,有 。
实现的话只需开两个指针维护 和 ,如果 ,那么将 加到 中,然后 移到下一个位置。如果 ,那么将 加到 中,然后 移到下一个位置。直到有一个序列的元素都加入到 中,最后只需把另外一个序列的剩余元素依次加到 中即可。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int a[N], b[N];
void solve() {
int n, m;
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++) {
scanf("%d", a + i);
}
for (int i = 0; i < m; i++) {
scanf("%d", b + i);
}
sort(b, b + m, greater<int>());
vector<int> ans;
for (int i = 0, j = 0; i < n || j < m; ) {
if (i < n && j < m) {
if (a[i] >= b[j]) ans.push_back(a[i++]);
else ans.push_back(b[j++]);
}
else if (i < n) {
ans.push_back(a[i++]);
}
else if (j < m) {
ans.push_back(b[j++]);
}
}
for (auto &x : ans) {
printf("%d ", x);
}
printf("\n");
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round 908 (Div. 1, Div, 2) Editorial:https://codeforces.com/blog/entry/122074
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17823458.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效