洛谷【AT2827】LIS
浅谈\(DP\):https://www.cnblogs.com/AKMer/p/10437525.html
题目传送门:https://www.luogu.org/problemnew/show/AT2827
\(LIS\)就是\(Longest\) \(Increasing\) \(Subsequence\),最长上升子序列问题。
给你一个序列\(a\),要你求最长上升子序列的长度。
我们可以把序列看做是一个个插数到序列尾部形成的,那么每插入一个新的数字,就是一个新的阶段。我们可以考虑用这个新插入的数字来做上升子序列的结尾,这个上升子序列会有多长。由于每次插入新的数字我们要做的事情都是一样的,所以这个问题就具有子问题重复性。由于我用这个新的数字结尾并不会影响到以以前数字结尾的子序列的长度,所以这个问题满足无后效性。并且,以当前这个数字为结尾的子序列的长度可以由在它之前的比它小的数字结尾的子序列长度得到,所以这个问题满足最优子结构性。于是我们就可以用\(DP\)来做了。
我们可以设立状态\(f_i\)表示以第\(i\)位数字结尾的上升子序列最长的长度是多少。一共有\(n\)个阶段,每次决策选择在\(i\)之前的比\(a_i\)小的数字来更新\(f_i\),状态转移方程就是:\(f_i=max(f_j+1)(0\leqslant j<i,a_j<a_i)\)。\(f\)初始均为\(0\),最后求出整个数组的最大值即为答案。
时间复杂度:\(O(n^2)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e3+5;
int n,ans;
int a[maxn],f[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
int main() {
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n;i++) {
for(int j=0;j<i;j++)
if(a[j]<a[i])
f[i]=max(f[i],f[j]+1);
ans=max(ans,f[i]);
}
printf("%d\n",ans);
return 0;
}
由于\(f_i\)只会由\(f_j+1\)更新得到(\(j\)是满足\(x<i\)且\(a_x<a_i\)的\(f_x\)最大的\(x\)),那么我们完全没有必要枚举没有用的位置,那样对于时间的浪费就太大。所以我们可以对于这个方程进行改进。
设\(f_i\)为以数字\(i\)结尾的最长上升子序列的长度。那么\(f_i=max(f_j+1)(0\leqslant j <i)\),因为我们的阶段还没有进行到\(i\)后面去,所以\(f_j\)表示的必然是\(i\)前面的某一个数字\(j\)结尾的上升子序列长度。这样子我们就可以用树状数组来维护\(f\)数组,每次查询前缀最大值\(+1\)来更新当前的\(f_{a_i}\),然后再在树状数组上改动相应的位置即可。如果序列的值域一开始不在\([1,n]\),那么我们离散化即可。
时间复杂度:\(O(nlogn)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
#define low(i) ((i)&(-(i)))
const int maxn=1e5+5;
int n,cnt;
int tmp[maxn],a[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct tree_array {
int c[maxn];
void change(int pos,int v) {
for(int i=pos;i<=cnt;i+=low(i))
c[i]=max(c[i],v);
}
int query(int pos) {
int res=0;
for(int i=pos;i;i-=low(i))
res=max(res,c[i]);
return res;
}
}T;
int main() {
n=read();
for(int i=1;i<=n;i++)
tmp[i]=a[i]=read();
sort(tmp+1,tmp+n+1);
cnt=unique(tmp+1,tmp+n+1)-tmp-1;
for(int i=1;i<=n;i++) {
a[i]=lower_bound(tmp+1,tmp+cnt+1,a[i])-tmp;
int f=T.query(a[i]-1)+1;
T.change(a[i],f);
}
printf("%d\n",T.query(n));
return 0;
}
洛谷【AT2827】LIS的更多相关文章
- 【模板】最长上升子序列(LIS)及其优化 & 洛谷 AT2827 LIS
最长上升子序列 传送门 题意 对于给定的一个n个数的序列,找到它的一个最长的子序列,并且保证这个子序列是由低到高排序的. 例如,1 6 2 5 4 6 8的最长上升子序列为1 2 4 6 8. 基本思 ...
- 洛谷 AT2827 LIS
题目传送门 解题思路: 用f[i]表示长度为i的最长上升子序列的最小的末尾. AC代码: #include<iostream> #include<cstdio> #includ ...
- P1091 合唱队形题解(洛谷,动态规划LIS,单调队列)
先上题目 P1091 合唱队形(点击打开题目) 题目解读: 1.由T1<...<Ti和Ti>Ti+1>…>TK可以看出这题涉及最长上升子序列和最长下降子序列 2 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- 【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]
以题写模板. 写了两个:n^2版本与nlogn版本 P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队 ...
- 洛谷1439 排列LCS问题
洛谷1439 排列LCS问题 本题地址:http://www.luogu.org/problem/show?pid=1439 题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输 ...
- 洛谷P3928 Sequence2(dp,线段树)
题目链接: 洛谷 题目大意在描述底下有.此处不赘述. 明显是个类似于LIS的dp. 令 $dp[i][j]$ 表示: $j=1$ 时表示已经处理了 $i$ 个数,上一个选的数来自序列 $A[0]$ 的 ...
- DP【洛谷P1704】 寻找最优美做题曲线
[洛谷P1704] 寻找最优美做题曲线 题目背景 nodgd是一个喜欢写程序的同学,前不久(好像还是有点久了)洛谷OJ横空出世,nodgd同学当然第一时间来到洛谷OJ刷题.于是发生了一系列有趣的事情, ...
- 洛谷1439:最长公共子序列(nlogn做法)
洛谷1439:最长公共子序列(nlogn做法) 题目描述: 给定两个序列求最长公共子序列. 这两个序列一定是\(1\)~\(n\)的全排列. 数据范围: \(1\leq n\leq 10^5\) 思路 ...
随机推荐
- 基于R语言的数据分析和挖掘方法总结——中位数检验
3.1 单组样本符号秩检验(Wilcoxon signed-rank test) 3.1.1 方法简介 此处使用的统计分析方法为美国统计学家Frank Wilcoxon所提出的非参数方法,称为Wilc ...
- android驱动USB摄像头
http://blog.csdn.net/mirkerson/article/details/50764314 多亏了stackoverflow看到的一篇帖子,其中有几句关键的话,然后顺藤摸瓜解决了问 ...
- Centos系统 上下文切换的检查思路
1.什么是上下文切换(Context Switch)? 上下文切换,有时也称做进程切换或任务切换,是指CPU从一个进程或线程切换到另一个进程或线程. 操作系统可以同时运行多个进程, 然而一颗CPU同时 ...
- 编写自已的第一个MapReduce程序
从进入系统学习到现在,貌似我们还没有真正开始动手写程序,估计有些立志成为Hadoop攻城狮的小伙伴们已经有些急了.环境已经搭好,小讲也有些按捺不住了.今天,小讲就和大家一起来动手编写我们的第一个Map ...
- Android系统--灯光系统驱动编写
Android系统开发--Android灯光系统tiny4412_led_class驱动编写 框架分析 led_classdev_4412结构体 创建led_classdev_4412结构体 分配结构 ...
- .NET CORE 动态调用泛型方法
using System; using System.Reflection; namespace DynamicCall { class Program { static void Main(stri ...
- Linux查看文件编码格式及文件编码转换<转>
如果你需要在Linux 中操作windows下的文件 ,那么你可能会经常遇到文件 编码 转换的问题.Windows中默认的文件 格式是GBK(gb2312),而Linux 一般都是UTF-8.下面介绍 ...
- Linux 基本命令___0002
来源:https://mp.weixin.qq.com/s/DmfpDfWpWRV3EDItDdYgXQ #配置vim #http://www.cnblogs.com/ma6174/archive/2 ...
- Flume-NG源码阅读之HBaseSink
关于HBase的sink的所有内容均在org.apache.flume.sink.hbase包下. 每个sink包括自己定制的,都extends AbstractSink implements Con ...
- windows下pip安装包权限的问题
md哔了狗了,把scipy弄崩了,还顺带把numpy弄崩了... 然后安装包一直权限不允许: 于是按照下面这篇博客以管理员运行cmd,结果还是没卵用 http://www.cnblogs.com/li ...