最长下降子序列O(n^2)及O(n*log(n))解法
求最长下降子序列和LIS基本思路是完全一样的,都是很经典的DP题目。
问题大都类似于 有一个序列 a1,a2,a3...ak..an,求其最长下降子序列(或者求其最长不下降子序列)的长度。
以最长下降子序列为例
用a[i]存储序列a的第i个元素(i: 1 to n)
用f[i]表示算上第i个位置的元素时最长子序列为f[i],
O(n^2)解法:
就是说在1 --- i -1之间必可以找到下标为j的元素a[j]使得f[j]是f[1]---f[i-1]之中最大的,则f[i] = f[j] + 1.
(注意要满足a[j]>a[i])
当i (1 to n)求得f[1] -- f[n]后只要再求得f[1]--f[n]之中最大的就是ans了。
状态转移方程:
f[i] = 1 (i = 1)//只有第一个字符
f[i] = f[j] + 1(a[i] < a[j] )//若是最长不下降则满足a[i] >= a[j].
代码实现:
//h[i]为母序列,dp[i]代表到第i个位置算上h[]i后得到的最长下降子序列长度ans是最长下降子序列长度
//f[i]代表到第i个位置算上h[]i后得到的最长不下降子序列长度min是最长不下降子序列长度
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std; #define maxint 0x7f7f7f7f
const int N = ; int h[N],dp[N],f[N];
int main(){
// freopen("in.txt","r",stdin);
// freopen(".txt","w",stdout);
int n = ;
int ans = -maxint,min = -maxint;
while(scanf("%d",&h[n]) != EOF){
n ++;
}
dp[] = f[] = ;
for(int i = ; i < n; i ++){
dp[i] = ;
f[i] = ;
for(int j = ; j < i; j ++){
if(dp[j]+>dp[i] && h[j] > h[i])
dp[i] = dp[j]+;
if(f[j]+>f[i] && h[j] < h[i])
f[i] = f[j]+;
}
}
for(int i = ; i < n; i ++){
if(ans<dp[i]){
ans = dp[i];
}
if(min<f[i])
min = f[i];
} printf("%d\n%d\n",ans,min); return ;
}
O(n*logn)解法
思路:
令数组c[k]记录使f[]= k时的a[i]的最小值,len表示此时最长下降子列的长度
在第i个位置有两种情况
1.a[i]<c[k],此时满足降序只需将a[i]接在c[k]后面,len +1;
2.a[i]>=c[k],则需要在a[1] 到c[k]之间找到一个大于它的最小值a[j],然后将a[i]置于j+1的位置,len = k = j+1.
由于c[k]不然具有单调性因而寻找a[j]的过程可以用二分。这也就是算法复杂度达到O(n*logn)的原因。
最后len的值也就是最长子序列的长度。
代码实现:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = ;
//二分查找返回大于a[i]的最小值的下标
int bSearch(int c[],int len,int n){
int left = ,right = len,mid;
while(left <= right){
mid = (left+right)/;
if(n > c[mid])
right = mid - ;
else if(n < c[mid])
left = mid + ;
else
return mid; }
return left;
} int a[N],c[N];
int main(){
int n = ,j,len;
int count = ;
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(scanf("%d",&a[n]) != EOF){
n ++;
}
c[] = a[];
len = ;
for(int i = ; i < n; i ++){
j = bSearch(c,len,a[i]);
c[j] = a[i];
if(j > len)//没找到,说明a[i]<c[k],根据二分查找的特点刚好j比len大一,将a[i]加到c[len+1]的位置
len = j;//更新len
}
printf(" ans = %d\n",len); return ;
}
最长下降子序列O(n^2)及O(n*log(n))解法的更多相关文章
- BUY LOW, BUY LOWER_最长下降子序列
Description The advice to "buy low" is half the formula to success in the bovine stock mar ...
- 【最长下降子序列】【动态规划】【二分】XMU 1041 Sequence
题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1041 题目大意: 一个二维平面,上面n(n<=1 000 000)个点.问至少选 ...
- 【最长下降子序列的长度和个数】 poj 1952
转自http://blog.csdn.net/zhang360896270/article/details/6701589 这题要求最长下降子序列的长度和个数,我们可以增加数组maxlen[size] ...
- POJ-1887 Testing the CATCHER(dp,最长下降子序列)
Testing the CATCHER Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 16515 Accepted: 6082 ...
- ZZNU 1719(最长上升子序列+最长下降子序列)
先吐血一发,噗! 再吐血一次,啊啊啊啊! 好吧,做了那么多次最长上升子序列,看这题看了半天才发现还有最长下降子序列,呵呵哒! AC代码: #include<stdio.h>//老恶心#in ...
- HDOJ(1069)最长下降子序列
每个箱子可有3种叠加方式,所以有3*n个箱子.将箱子按长度由大到小排序,有求箱子按宽度的最长下降子序列的高度之和即可. #include<cstdio> #include<algor ...
- 九度OJ 1112:拦截导弹 (DP、最长下降子序列)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3124 解决:1525 题目描述: 某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能 ...
- hdu1160简单dp最长下降子序列
/* 简单dp,要记录顺序 解:先排序,然后是一个最长下降子序列 ,中间需记录顺序 dp[i]=Max(dp[i],dp[j]+1); */ #include<stdio.h> #incl ...
- POJ 1836 Alignment(DP max(最长上升子序列 + 最长下降子序列))
Alignment Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14486 Accepted: 4695 Descri ...
随机推荐
- zabbix安装配置界面点击next step没反应
修改/var/lib/php/session/宿主或者添加777权限 看到有个人说这个不能用,一开始我也没用,找了各种方式都不行,最后死马当作活马医,改了下权限,卧槽,一下子就OK了,日
- 升级python
一开始有这个需求,是因为用 YaH3C 替代 iNode 进行校园网认证时,一直编译错误,提示找不到 Python 的某个模块,百度了一下,此模块是在 Python2.7 以上才有的,但是系统的自带的 ...
- Java学习笔记__异常机制_try_catch_finally_return执行顺序
package cn.xiaocangtian.Exception; import java.io.FileInputStream; import java.io.FileNotFoundExcept ...
- hdu 2222 Keywords Search
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:裸AC自动机,直接贴代码做模板 #include<stdio.h> #includ ...
- java中Inetaddress类
InetAddress类 InetAddress类用来封装我们前面讨论的数字式的IP地址和该地址的域名. 你通过一个IP主机名与这个类发生作用,IP主机名比它的IP地址用起来更简便更容易理解. Ine ...
- Html和CSS布局技巧
单列布局水平居中 水平居中的页面布局中最为常见的一种布局形式,多出现于标题,以及内容区域的组织形式,下面介绍四种实现水平居中的方法(注:下面各个实例中实现的是child元素的对齐操作,child元素的 ...
- JS挂马攻防
JS挂马攻防实录 攻现在最多见的JS挂马方法有两种,一种是直接将JavaScript脚本代码写在网页中,当访问者在浏览网页时,恶意的挂马脚本就会通过用户的浏览器悄悄地打开网马窗口,隐藏地运行(图1), ...
- axure的一些注意事项
1. 不要轻易用中继器的 载入时 事件, 感觉存在bug 2. 元件在显示和隐藏的动画过程中,不要去取他的x,y值,有几率会取成0,也不要去获取它的尺寸,只有在动画完成后才能获得 3. 装着一个中继器 ...
- "不能在 DropDownList 中选择多个项。"其解决办法及补充
探讨C#.NET下DropDownList的一个有趣的bug及其解决办法 摘要: 本文就C#.Net 环境下Web开发中经常使用的DropDownList控件的SelectedIndex属性进行了详细 ...
- Android四种点击事件和五中存储方式
Android点击事件的四种实现方式 1.内部类实现onClickListenter接口 bt_login.setOnClickListener(new MyListener()); class My ...