动态规划入门 COGS1398 最长上升子序列
来源:互联网 发布:linux shell 打印变量 编辑:程序博客网 时间:2024/06/03 14:31
1398. 最长上升子序列
★ 输入文件:lis1.in
输出文件:lis1.out
简单对比
时间限制:1 s 内存限制:256 MB
【题目描述】
设有整数序列A[1],A[2],A[3],…,A[m],若存在下标i1<i2<i3<…<in,且A[i1]<A[i2]<A[i3]<…<A[in],则称 序列A[1],A[2],A[3],…,A[m]中有长度为n的上升子序列A[i1] , A[i2] ,A[i3] ,…,A[in]。
请编程计算指定序列的最长上升子序列长度。
【输入格式】
第一行一个正整数n(n<1001),表示序列中整数个数;
第二行是空格隔开的n个整数组成的序列。
【输出格式】
一个正整数,表示输入文件中整数序列的最长上升子序列的长度。
【样例输入】
7
1 7 3 5 9 4 8
【样例输出】
4
【样例说明】
- 序列(1,7,3,5,9,4,8)最长上升序列有:(1,3,5,9),(1,3,5,8),(1,3,4,8),他们长度为4。
- 方程为f(i)=max{f(j)}+1(b
j
- <b
i
- 且i<j)
- 这个题重在优化
- 首先先贴LIS代码
- 注意要赋到f[]数组初值(某小受就没有)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 7 int n; 8 int in[10010],f[10010]; 9 int ans;10 11 int main(){12 scanf("%d",&n);13 for(int i=1;i<=n;i++) scanf("%d",&in[i]),f[i]=1;14 for(int i=2;i<=n;i++){15 for(int j=1;j<i;j++)16 if(in[i]>in[j]) f[i]=max(f[i],f[j]+1);17 ans=max(ans,f[i]);18 }19 printf("%d",ans);20 return 0;21 }
单调栈优化
从前向后扫描序列列,维护一个单调栈
插⼊入一个数时,我们在h[] 中二分出一个位置i,使得h[i]<a[k+1]<=h[i + 1],令h[i+1]=a[k + 1] 即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 int n; 8 int num[10010]; 9 int top;10 int tmp;11 12 void add(int t){13 if(t>num[top]) num[++top]=t;14 else{15 int ll=1;16 int rr=top;17 int mid;18 while(ll<=rr){19 mid=(ll+rr)>>1;20 if(t>num[mid]) ll=mid+1;21 else rr=mid-1;//注意-1和+122 }23 num[ll]=t;24 }25 return;26 }27 28 int main(){29 scanf("%d",&n);30 num[0]=-1;31 for(int i=1;i<=n;i++) scanf("%d",&tmp),add(tmp);32 printf("%d",top);33 return 0;34 }
树状数组优化
数组离散化并用树状数组维护前缀最大值
1 //实为最长上升子序列 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 8 int n; 9 int in[10010],val[10010];10 int len;11 int b[10010];//b[i]以数字i结尾的子序列最长可以为的值 12 //扫描到in[k]这个位置时,b[i]中只有b[a[k]]会改变13 //b[a[k]]=max(b[i]+1|i<a[k]) 14 int ans,temp;15 16 void add(int v,int pos){17 for(int i=pos;i<=len;i+=i&(-i)) b[i]=max(v,b[i]);18 return; 19 }20 21 int ask(int pos){22 int t=0;23 for(int i=pos;i;i-=i&(-i)) t=max(t,b[i]);24 return t;25 } 26 27 int main(){28 scanf("%d",&n);29 for(int i=1;i<=n;i++) scanf("%d",&in[i]),val[i]=in[i];30 sort(val+1,val+n+1);31 len=unique(val+1,val+n+1)-val;//去重 保证最长上升32 memset(b,0,sizeof(b));33 ans=1;34 for(int i=1;i<=n;i++){35 in[i]=lower_bound(val+1,val+len+1,in[i])-val+1;//离散化???高大上 36 temp=ask(in[i]-1)+1;37 ans=max(ans,temp);38 add(temp,in[i]);39 }40 printf("%d",ans);41 }
线段树优化
可以用树状数组优化,那么显然可用线段树
然而我码了2K挂掉了,以后再补
阅读全文
0 0
- 动态规划入门 COGS1398 最长上升子序列
- cogs1398 最长上升子序列 动态规划初级
- 动态规划:最长上升子序列
- 动态规划-最长上升子序列LIS
- 动态规划求最长上升子序列
- 【算法】动态规划 最长上升子序列
- 动态规划:最长上升子序列
- poj2533 动态规划+最长上升子序列
- POJ2533 动态规划 (最长上升子序列)
- 动态规划--最长上升子序列
- 动态规划-最长上升子序列【LIS】
- 动态规划之最长上升子序列
- 动态规划 LIS最长上升子序列
- 动态规划-最长上升子序列
- 动态规划:求最长上升子序列
- 动态规划-最长上升子序列
- 动态规划(最长上升子序列)
- 动态规划:最长上升子序列
- 线段树 洛谷P1531 I Hate It
- 平衡树之splay BZOJ3224 普通平衡树
- 树状数组 HNOI2002 营业额统计
- 树状数组 NOIP2013 火柴排队
- 最小生成树 HZOI 2016公路修建
- 动态规划入门 COGS1398 最长上升子序列
- 动态规划入门 P1115 最大子段和(链状)
- 动态规划入门 TYVJ 1305 最大子段和(环状)
- KMP kmp模板
- 关于spring的事务面试题
- 状压DP HDU3538 A sample Hamilton path
- 树形DP Tyvj1052 没有上司的舞会
- 动态规划入门 洛谷P1020 拦截导弹
- 状压DP SCOI2005 互不侵犯King