LIS.LCS.LCIS相关问题

news2025/7/15 1:25:17

文章目录

  • P1020 [NOIP1999 普及组] 导弹拦截
  • P1439 【模板】最长公共子序列
  • P1637 三元上升子序列
  • 272. 最长公共上升子序列
  • LCIS

在这里插入图片描述

P1020 [NOIP1999 普及组] 导弹拦截

P1020 [NOIP1999 普及组] 导弹拦截

导弹拦截应该是接触DP的第一题(只不过洛谷上的数据加强了,按照上图的 O ( N 2 ) O(N^2) O(N2)做法过不去QAQ可以改用二分。

Dilworth定理:偏序集能划分成的最少的全序集个数等于最大反链的元素个数

把一个数列划分成最少的最长不升子序列的数目就等于这个数列的最长上升子序列的长度(LIS)

#include<bits/stdc++.h> 
using namespace std;
int a[100010],LDS[100010],LIS[100010];
int main()
{
	int x,i=0,len=1;
	while(~scanf("%d",&x))
		a[i++]=x;
	LDS[0]=a[0];
	for(int j=1;j<i;j++)
	{
		if(a[j]<=LDS[len-1])
			LDS[len++]=a[j];
		else
		{
			int l=0,r=len;
			while(l<r)
			{
				int mid=(l+r)>>1;
				if(a[j]>LDS[mid]) r=mid;
				else l=mid+1;
			}
			LDS[l]=a[j];
		}
	}
	cout<<len<<endl;
    LIS[0]=a[0];
    int len2=1;
	for(int j=1;j<i;j++)
	{
		if(a[j]>LIS[len2-1])
			LIS[len2++]=a[j];
		else
		{
			int l=0,r=len2;
			while(l<r)
			{
				int mid=(l+r)>>1;
				if(a[j]<=LIS[mid]) r=mid;
				else l=mid+1;
			}
			LIS[l]=a[j];
		}
	}
	cout<<len2<<endl;
    return 0;
}

P1439 【模板】最长公共子序列

P1439 【模板】最长公共子序列

也不给你用上图的朴素DP过去( O ( N 2 ) O(N^2) O(N2))www

for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
     {
     	dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
     	if(a1[i]==a2[j])
     	dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
     }
   cout<<dp[n][m];

但本题数据有个明显的特征即两个序列都是全排列,也就是说我们可以重新构造一种映射关系。

#include<bits/stdc++.h> 
using namespace std;
int a[100010],b[100010],LIS[100010];
int main()
{
	int n,i;
	cin>>n;
	//由于a b 中元素完全相同,只是顺序不同,可以利用映射关系,将a映射成一个单调递增序列 
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		a[x]=i;
	}
	//相应地,由a给出的映射关系,可将b构造成一个新的序列 
	for(int i=1;i<=n;i++)
	{
		int y;
		scanf("%d",&y);
		b[i]=a[y];
	}
	// 两个序列的子序列,一定是a的子序列。而a本身就是单调递增的。因此这个子序列是单调递增的。
	//换句话说,只要这个子序列在b中单调递增,它就是a的子序列
    //哪个最长呢?当然是b的LIS最长。下用二分+贪心求b的LIS即可 
	LIS[1]=b[1];
    int len2=1;
	for(int j=2;j<=n;j++)
	{
		if(b[j]>LIS[len2])
			LIS[++len2]=b[j];//如果此时检索到的数比LIS的最后一个数(也即最大的数)大,直接插到LIS尾部 
		else//否则,在LIS前面的数中二分查找合适的位置进行替换 
		{
			int l=1,r=len2;
			while(l<r)
			{
				int mid=(l+r)>>1;
				if(b[j]<=LIS[mid]) r=mid;
				else l=mid+1;
			}
			LIS[l]=b[j];
		}
	}
	cout<<len2<<endl;
    return 0;
}

P1637 三元上升子序列


P1637 三元上升子序列
UVA12983 The Battle of Chibi

给定一个长度为n的序列,求其包含的m元单调上升子序列个数。
见求LIS思DP。导弹拦截那种题,开f[结尾编号]=序列长度,信息量不够,考虑定义f[序列长度][结尾编号] =序列个数。

状态转移: f [ i ] [ j ] = ∑ f [ i − 1 ] [ k ] , 1 < = k < j , a [ k ] < a [ i ] f[i][j]=\sum f[i-1][k],1<=k<j,a[k]<a[i] f[i][j]=f[i1][k],1<=k<j,a[k]<a[i]

这样做的时间复杂度为 O ( n 2 ∗ m ) O(n^2*m) O(n2m)

得想办法在更短时间内统计出 ∑ f [ i − 1 ] [ k ] \sum f[i-1][k] f[i1][k],树状数组或者线段树都可以实现在 O ( l o g n ) O(log n) O(logn)内的区间统计。

先离散化,将a[]的分布集中起来,以a[k]为下标储存f[i-1][k]的值。

此时针对状态转移方程写两层循环:外层循环枚举长度,每次枚举到一个长度都重置一下树状数组c[]。{内层枚举序列结尾坐标,此前已将f[i-1][k]增加到树状数组中,此时只需用树状数求和即可。然后把f[i-1][j]加到树状数组中,这个值只会更新到比a[j]大的数(对应状态转移方程里的a[k]<a[i]),这些数后续会被调用(对应状态转移方程里的1<=k<j)}。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=30010;
ll n,f[4][N],a[N],b[N],c[N],ans;

ll lowbit(ll x) { return x&(-x);}

void update(ll p,ll v)
{
	for(int i=p;i<=n;i+=lowbit(i))
		c[i]+=v;
} 

ll ask(int p)
{
	ll sum=0;
	for(int i=p;i;i-=lowbit(i))
		sum+=c[i];
	return sum;
}

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]),b[i]=a[i];
	sort(b+1,b+n+1);
	unique(b+1,b+n+1)-(b+1);
	for(int i=1;i<=n;i++)
	{
		a[i]=lower_bound(b+1,b+n+1,a[i])-b;//二分查找在数组中的位置
		f[1][i]=1;//初始化:长度唯一,本身为结尾
	}
	//离散化结束,初始化结束,准备工作完成
	for(int i=2;i<=3;i++)//枚举长度
	{
		memset(c,0,sizeof(c));//重置树状数组
		for(int j=1;j<=n;j++)
		{
			f[i][j]=ask(a[j]-1);//求和
			update(a[j],f[i-1][j]);//更新
		}
	}
	for(int i=1;i<=n;i++)
		ans+=f[3][i];
	cout<<ans; 
    return 0;
}


272. 最长公共上升子序列

272. 最长公共上升子序列

定义 f [ i ] [ j ] f[i][j] f[i][j]: a [ 1 ] − a [ i ] , b [ 1 ] − b [ j ] a[1]-a[i],b[1]-b[j] a[1]a[i],b[1]b[j]可以构成的以 b [ j ] b[j] b[j]结尾的LCIS的长度。

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int f[N][N];
int n,a[N],b[N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            f[i][j]=f[i-1][j];
            if(a[i]==b[j])
            {
               int maxv=1;
                for (int k=1;k<j;k++)
                    if (a[i]>b[k]) maxv=max(maxv, f[i - 1][k] + 1);
                f[i][j]=max(f[i][j], maxv);
            }
        }
    int ans=0;
    for(int j=1;j<=n;j++)
        ans=max(ans,f[n][j]);
    cout<<ans<<endl;
    return 0;
}

TLE了,发现可以没必要枚举k,可以用val实时更新长度。

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int f[N][N];//a1~ai,b1~bj可以构成的以bj结尾的LCIS的长度
int n,a[N],b[N],ans=0,m;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)
    {
        int val=0;//(i,0)的LCIS长度
        //i固定,b1->bn时LCIS长度一定是单调递增的
        for(int j=1;j<=n;j++)
        {
            if(a[i]==b[j]) f[i][j]=val+1;//遍历到一个ai、bj相同的位置,长度++
            else f[i][j]=f[i-1][j];//不相等,直接继承(i-1,j)的长度
            if(b[j]<a[i]) val=max(val,f[i-1][j]);//更新val:(i,j)前面的LCIS长度
            //另一种情况:(b[j]>a[i])一定不会影响到LCIS的长度
        }
    }
    for(int j=1;j<=n;j++)//找出所有以bj结尾的LCIS中长度最大的
        ans=max(ans,f[n][j]);
    cout<<ans<<endl;
    return 0;
}

进一步发现f的第一维也是可以省略的。

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int f[N];//a1~ai,b1~bj可以构成的以bj结尾的LCIS的长度
int n,a[N],b[N],ans=0,m;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)
    {
        int val=0;//(i,0)的LCIS长度
        //i固定,b1->bn时LCIS长度一定是单调递增的
        for(int j=1;j<=n;j++)
        {
            if(a[i]==b[j]) f[j]=val+1;//遍历到一个ai、bj相同的位置,长度++
            if(b[j]<a[i]) val=max(val,f[j]);//更新val:(i,j)前面的LCIS长度
            //另一种情况:(b[j]>a[i])一定不会影响到LCIS的长度
        }
    }
    for(int j=1;j<=n;j++)//找出所有以bj结尾的LCIS中长度最大的
        ans=max(ans,f[j]);
    cout<<ans<<endl;
    return 0;
}

LCIS

LCIS

加上路径输出。

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int f[N];//a1~ai,b1~bj可以构成的以bj结尾的LCIS的长度
int n,a[N],b[N],ans[N],m,scheme[N],p;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    cin>>m;
    for(int i=1;i<=m;i++)
        scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)
    {
		int id=0;
        //i固定,b1->bn时LCIS长度一定是单调递增的
        for(int j=1;j<=m;j++)
        {
            if(a[i]==b[j]) f[j]=f[id]+1,scheme[j]=id;
			//遍历到一个ai、bj相同的位置,长度++,记录下j前面一个位置是id 
            if(b[j]<a[i]&&f[id]<f[j]) id=j;
        }
    }
    int p=0;
    for(int i=1;i<=m;i++)
        if(f[i]>f[p]) p=i;//找出所有以bj结尾的LCIS中长度最大的
    printf("%d\n",f[p]);
    int top=0;
    while(f[p]--) 
	{
        ans[++top]=b[p];
        id=scheme[p];//从后往前倒出来 
    }
    for(int i=top;i;i--)
        printf("%d ",ans[i]);//输出方案前需要记录
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/8481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows平台 使用jarsigner对Apk签名

使用的是JDK自带的jarsigner工具来完成Apk签名 1) 首先找到你的Java Jdk中bin的路径&#xff1a;C:\Program Files\Java\jdk1.8.0_152\bin jarsigner简单使用说明 #jarsigner的命令格式&#xff1a; jarsigner -verbose -keystore [您的私钥存放路径] -signedjar [签名后文件存…

使用高数值孔径透镜进行脉冲聚焦

摘要 尽管对于大多数其他类型的光源而言&#xff0c;静态近似下是足够精确的&#xff0c;但对于超短脉冲来说需要更加精确的方法&#xff0c;其中要考虑到不同光谱模式之间的相关性。在此&#xff0c;我们在空间、时间与场分布上研究了该脉冲传播通过高数值孔径透镜的影响。 建…

基于matlab和Simulink的不同阶QAM调制解调系统误码率对比仿真

目录 1.算法概述 2.仿真效果预览 3.核心MATLAB预览 4.完整MATLAB程序 1.算法概述 正交振幅调制是利用已调信号在相同带宽内的频谱正交来实现两路并行的数据信息传输&#xff0c;其信道频带利用率与单边带调制一样&#xff0c;主要用于高速数据传输系统中。QAM系统组成框图如…

Vue3 - 事件 API 新标准(如何在 Vue3 中怎么用事件总线实现兄弟组件通信?相比 Vue2 有什么不同?)

前言 对比 Vue2 &#xff0c;引出并展开 Vue3 。 本文讲述了事件 API 在 Vue3 中相比 Vue2 有什么变化&#xff0c;以及使用方法和代码示例详细讲解。 回忆 Vue2 大家在写 Vue2 项目时&#xff0c;兄弟组件之间传参&#xff0c;我相信很大一部分开发者都会借助全局的事件总线&…

Kubernetes 系统化学习之 POD原理篇(二)

1. Kubernets 概览回顾 Pod、Service、Volume 和 Namespace 是 Kubernetes 集群中四大基本对象&#xff0c;它们能够表示系统中部署的应用、工作负载、网络和磁盘资源&#xff0c;共同定义了集群的状态。Kubernetes 中很多其他的资源其实只对这些基本的对象进行了组合。 Pod -…

最全JAVA系列视频教程源码

扫描关注公众号&#xff1a;发送对应消息获取源码&#xff08;下面红色字为发送消息内容,取掉空格哦&#xff09; JAVA 基础&#xff1a; java基础 更适合零基础学员&#xff1a; 自Java语言起源始&#xff0c;循序渐进&#xff0c;知识点剖析细致且每章配备大量随堂练…

Android实现动态换肤-原理篇

学习是一个过程。 文章目录Activity中LayoutInflater加载布局总体时序图LayoutInflater源码讲解&#xff08;api28&#xff09;LayoutInflater设置Factory2实现方式LayoutInflater源码总结Activity中LayoutInflater加载布局总体时序图 LayoutInflater源码讲解&#xff08;api28…

高级UI——Paint(滤镜,颜色通道,矩阵运算)

前言 我们已经详细了解到整个android程序&#xff0c;从启动再到绘制的整体流程&#xff0c;从这中间我们又牵扯出了Canvas绘制图形的画板和我们的Paint控制色彩样式的画笔&#xff0c;那么之前基础篇我们就不进行详细的解释&#xff0c;那些API在之前的基础篇已经公布出来&am…

Typescript 函数类型详解

Typescript 函数 前言 虽然 JS/TS 支持面向对象编程&#xff0c;但大部分时候还是在写函数。函数是一等公民。本文介绍下如何在 TypeScript 中使用函数&#xff0c;包括&#xff1a; 函数类型声明函数参数类型&#xff1a;可选参数、默认参数、剩余参数函数返回值类型this 类…

java#5(数组)

目录 数组 1.数组的完整格式:数据类型[] 数组名 new 数据类型[]{元素1,元素2......}; 2.数组的简化格式:数据类型[] 数组名 {元素1,元素2......}; 3.数组的地址​编辑 4.数组的索引(下标,角标) 5.length的使用(表示数组的长度:有几个元素) 6.数组动态初始化:初始化时指…

Redis事务入门及命令

文章目录Redis 事务入门及命令事务概念Redis 事务概念Redis 事务特性Redis 三个阶段入门代码示例Redis 相关命令MULTIDISCARDEXECWATCHUNWATCHRedis 事务入门及命令 事务概念 数据库事务( transaction )是访问并可能操作各种数据项的一个数据库操作序列&#xff0c;这些操作要…

详解 YUV,一文搞定 YUV 是什么!

YUV 是一个颜色模型&#xff0c;通常用作彩色图像管道的一部分。它对彩色图像或视频进行编码时考虑到了人类的感知&#xff0c;与“直接”的 RGB 表示相比&#xff0c;允许减少色度分量的带宽。历史上&#xff0c;术语 YUV 和 Y’UV 用于电视系统中颜色信息的特定模拟编码。今天…

HTML学生作业网页:使用HTML+CSS技术实现传统文化网页设计题材-西安事变历史纪念馆 10页 带视频 带音乐

Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 茶文化网站 | 中华传统文化题材 | 京剧文化水墨风书画 | 中国民间年画文化艺术网站 | HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&#xff1a;样式 在操作方面上运…

《上海悠悠接口自动化平台》-4.注册用例集实战演示

前言 以注册接口为例&#xff0c;在平台上演示如何维护接口自动化用例 访问地址http://47.108.155.10/login.html 用户名: demo, 密码: demo123 有兴趣的可以自己去查看用例规范 和 运行效果。 API 接口层 先找出注册接口的接口文档&#xff0c;以下是接口文档部分 主要关…

Redis配置哨兵及其机制

目录一、Redis哨兵诞生背景二、关于哨兵三、哨兵机制的基本流程3.1 监控3.2 选主3.3 通知四、关于主观下线和客观下线4.1 主观下线4.2 客观下线五、选主规则3.1 优先级最高的从库得分高3.2 和旧主库同步程度最接近的从库得分高3.3 ID 号小的从库得分高六、配置流程七、总结一、…

网络面试-0x10地址栏输入URL敲入回车后发生了什么?

一、 URL解析 1、 首先判断你输入的是一个合法的URL还是待搜索的关键字 2、如果是URL&#xff0c;对URL进行解析 二、 DNS查询 1、设备 —— 本地DNS服务器 —— xx 递归过程 2、DNS服务器和 顶级域名服务器、二级域名服务器、权威域名服务器之间是迭代过程。 三、 TCP连接 …

redis和selery相关知识点

目录标题一&#xff1a;redis字符串操作二&#xff1a;redis hash操作三&#xff1a;redis列表操作四&#xff1a;redis管道1.redis数据库&#xff0c;是否支持事务&#xff1f;2.redis代码实现事务五&#xff1a;redis其他操作六&#xff1a;django中集成redis1.方式一:直接使…

用python就获取到照片拍摄时的详细位置【源码公开】

文章目录一.引言1.读取照片信息&#xff0c;获取坐标2.通过baidu Map的API将GPS信息转换成地址。二.源码附上&#xff01;&#xff01;&#xff01;注意事项一.引言 先看获取到的效果 拍摄时间&#xff1a;2021:12:18 16:22:13 照片拍摄地址:(内蒙古自治区包头市昆都仑区, 内…

pytorch从零开始搭建神经网络

目录 基本流程 一、数据处理 二、模型搭建 三、定义代价函数&优化器 四、训练 附录 nn.Sequential nn.Module model.train() 和 model.eval() 损失 图神经网络 基本流程 《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibili1. 数据预处理&#xff08;Dataset、…

由浅入深,一起来刷Java高级开发岗面试指南,明年面试必定无忧!

前言 我只想面个CV工程师&#xff0c;面试官偏偏让我挑战造火箭工程师&#xff0c;加上今年这个情况更是前后两男&#xff0c;但再难苟且的生活还要继续&#xff0c;饭碗还是要继续找的。在最近的面试中我一直在总结&#xff0c;每次面试回来也都会复盘&#xff0c;下面是我根…