题解:CF1893B Neutral Tonality
CF1893B 题解
题面
题意
给定两个数组 a,b,构造一个序列 c,使得其包含 a,b 中的所有元素,保证 a 在其中的相对顺序不变,且最长(严格)上升子序列(LIS(c))最短。
转化一下,也可以理解为,给定两个数组 a,b,要求把 b 中的所有元素按照任意顺序插入 a 中,要求最终形成的数组的最长(严格)上升子序列最短。
思路
首先因为 a 在 c 中的相对位置不变,所以必然有 LIS(c)⩾LIS(a)。
那么就考虑如何插入 b 可以使得 LIS(c)=LIS(a),容易想到一种简单的构造方法,现将 b 从大到小排序,对于一个数 b[j],将它插入到第一个满足 a[i]⩽b[j] 的 a[i] 前面,那为什么这样是 LIS(c)=LIS(a) 的呢?接下来开始证明。
首先,因为是插入到第一个满足 a[i]⩽b[j] 的 a[i] 前面,所以在 a[i] 前面的所有数都小于 b[j],但是因为 a[i]⩽b[j],所以对于一个上升子序列,选 a[i] 肯定更优(至少是一样),要是有多个数插在同一个位置也不会影响答案,因为 b 已经被从大到小排序过,所以每次的插入不会改变序列的最长(严格)上升子序列。
那么,开始打代码吧~
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int MN=200005;
ll T,n,m,a[MN],b[MN];
bool cmp(ll x, ll y){return x>y;}
void write(ll n){if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
int main(){
T=read();while(T--){
n=read();m=read();for(int i=1; i<=n; i++) a[i]=read();for(int i=1; i<=m; i++) b[i]=read();
sort(b+1,b+1+m,cmp);//从大到小排序
for(int i=1,p1=1,p2=1; i<=n+m; i++){
if(p1>n||(p2<=m&&b[p2]>=a[p1])) write(b[p2++]),putchar(' ');
else write(a[p1++]),putchar(' ');
}
putchar('\n');
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】