poj 2533(最长上升子序列)(n^2 ) 和 nlogn的算法
2013-08-26 15:27
302 查看
题目链接:点击打开链接
题目大意:略
题目分析:1.用n平方的做法,枚举以data【i】为结尾的子序列,向前查找,比data【i】小并且dp【j】比dp【i】小的
新手代码:
测试样例
5
1 2 1 4 1
6
1 1 2 2 1 1
6
1 6 2 3 7 5
2. 二分法nlogn+栈+替换 参考:点击打开链接
备注:这种方法适用于求数目,没有真正求出具体的字串
除此之外:其实不用栈
使用函数lower_bound()
函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置
举例如下:
一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标
则
pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。
pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。
pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。
所以,要记住:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!~
返回查找元素的第一个可安插位置,也就是“元素值>=查找值”的第一个元素的位置
关于lower_bound() 详见:点击打开链接
题目大意:略
题目分析:1.用n平方的做法,枚举以data【i】为结尾的子序列,向前查找,比data【i】小并且dp【j】比dp【i】小的
新手代码:
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> using namespace std; const int maxn=1005; int data[maxn],dp[maxn]; int main() { int n,i,j,ans; while(~scanf("%d",&n)) { for(i=0;i<n;i++) scanf("%d",&data[i]); ans=1; for(i=0;i<n;i++) { dp[i]=1;//注意!! for(j=i;j>=0;j--) if(data[j]<data[i]&&dp[j]+1>dp[i]){dp[i]=dp[j]+1;} if(dp[i]>ans) ans=dp[i]; } printf("%d\n",ans); } return 0; }
测试样例
5
1 2 1 4 1
6
1 1 2 2 1 1
6
1 6 2 3 7 5
2. 二分法nlogn+栈+替换 参考:点击打开链接
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; const int maxn=1005; int stack[maxn]; int main() { int n,i,top,data,j; while(~scanf("%d",&n)) { top=0;stack[0]=-1;//注意栈首 for(i=0;i<n;i++) { scanf("%d",&data); if(data>stack[top]) stack[++top]=data; else { int l=1,r=top,mid; while(l<=r) { mid=(l+r)/2; if(data>stack[mid]) l=mid+1; else r=mid-1; } stack[l]=data; } } printf("%d\n",top); } }
备注:这种方法适用于求数目,没有真正求出具体的字串
除此之外:其实不用栈
使用函数lower_bound()
函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置
举例如下:
一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标
则
pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。
pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。
pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。
所以,要记住:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!~
返回查找元素的第一个可安插位置,也就是“元素值>=查找值”的第一个元素的位置
关于lower_bound() 详见:点击打开链接
#include<stdio.h> #include<string.h> #include<algorithm> #define max 10005 using namespace std; int main() { int data[max],a[max],n,i; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&data[i]); } int top=0;a[top]=-1; for(i=1;i<=n;i++) { if(data[i]>a[top]) a[++top]=data[i]; else { int pos=lower_bound(a+1,a+1+top,data[i])-a; a[pos]=data[i]; } } printf("%d\n",top); return 0; }
相关文章推荐
- POJ 2533 Longest Ordered Subsequence(最长上升子序列(NlogN)
- POJ 2533 Longest Ordered Subsequence(最长上升子序列(NlogN)
- hdu 1025 Constructing Roads In JGShining's Kingdom(最长上升子序列(LIS)O(nlogn)算法)
- 最长上升子序列 nlogn时间复杂度 poj 2533
- [算法] poj 3903 最长上升子序列 dp vs (二分 nlogn)
- [算法] poj 3903 最长上升子序列 dp vs (二分 nlogn)
- hdu 1025 Constructing Roads In JGShining's Kingdom(最长上升子序列(LIS)O(nlogn)算法)
- poj 1631 / nlogn 算法 求 最长上升子序列长度
- POJ 2533 Longest Ordered Subsequence(最长上升子序列长度、O(nlogn))
- POJ2533 -Longest Ordered Subsequence最长上升子序列-动规和nlogn二分算法详解
- 最长上升子序列 POJ2533
- 最长上升子序列 POJ 2533(n*n与 nlogn)
- 最长递增子序列(LIS)的O(NlogN)打印算法
- 最长单调子序列(O(n^2) 和 O(nlogn) 算法)
- POJ 2533 最长上升子序列 [动态规划 + 二分搜索]
- 最长上升子序列 POJ 2533(n*n与 nlogn)
- 杭电ACM OJ 1025 Constructing Roads In JGShining's Kingdom 最长上升子序列 O(nlogn)算法详解+回溯暴力解决+动态规划dp优雅解决
- Longest Ordered Subsequence【POJ 2533 dp 最长不降子序列】
- {POJ}{3903}{Stock Exchange}{nlogn 最长上升子序列}
- 最长单调递增子序列O(NlogN)算法