题解:CF1893B Neutral Tonality

CF1893B 题解

题面

原题传送门

题意

给定两个数组 a,b,构造一个序列 c,使得其包含 a,b 中的所有元素,保证 a 在其中的相对顺序不变,且最长(严格)上升子序列(LIS(c))最短。

转化一下,也可以理解为,给定两个数组 a,b,要求把 b 中的所有元素按照任意顺序插入 a 中,要求最终形成的数组的最长(严格)上升子序列最短。

思路

首先因为 ac 中的相对位置不变,所以必然有 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;
}
posted @   naroto2022  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
唯有信仰与日月亘古不灭。