nlogn求最长上升子序列 (POJ2533)
2017-05-14 15:23
232 查看
nlogn求最长上升子序列 (POJ2533)
Description
求最长上升子序列。题解
LIS裸题,但我这里想讲一下nlogn的做法。其实我们可以发现,在通常的LIS算法中的的二个循环的过程中,为了寻找最大值,做了很多无用功。
于是,我们可以用一个单调栈来作为决策列表,用logn的时间来找到最优决策。
对于一个数,如果其大于栈定元素,就将其加入栈,以其结尾的答案就是栈的大小。这就代表着这个数可以取之前栈定元素作为决策,所以长度为之前栈定元素的长度加一。于是,这个数也成为这个长度下第一个也是目前唯一一个决策来入栈。
如果这个数小于栈定,用lower_bound来找到栈第一个大于等于这个数的元素,令其为栈中序号为k,这个数的长度就算k-1的长度加一,也就是k的长度。
因为这个数有比找到数的值小,将其着为以后的决策当然可以更优,我们就用它来替换找到的数。
这样维护了一个单调的决策栈,可以花logn的时间决策,总复杂度为nlogn。
答案就算栈的大小,也就是以栈定元素结尾的大小。
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #define MAXN 1000000+10 using namespace std; int n,a[MAXN],f[MAXN],ans=1,top=1; int s[MAXN],d[MAXN]; int main() { while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); memset(s,0,sizeof(s)); ans=1;top=1;s[top]=a[1]; for(int i=2;i<=n;i++) { if(a[i]>s[top]) s[++top]=a[i]; else s[lower_bound(s+1,s+top+1,a[i])-s]=a[i]; } printf("%d\n",top); } return 0; }
相关文章推荐
- ACdream 1216 Beautiful People(二路最长上升子序列 O(nlogn) )
- 最长上升子序列(LIS)长度的O(n^2)与O(nlogn)算法
- nlogn 求最长上升子序列 LIS
- 最长上升子序列(LIS)长度的O(nlogn)算法
- 最长上升子序列 POJ2533
- <序列DP>O(nlogn)的最长上升子序列
- 最长上升子序列(nlogn)
- 最长上升子序列 (二分 nlogn)
- HDU 5748 Bellovin(最长上升子序列[nlogn])
- 最长上升子序列 nlogn时间复杂度 poj 2533
- 最长上升子序列 Longest Increasing Subsequence 输出其中一个序列 O(n^2) O(nlogn)
- 最长上升子序列(LIS)长度的O(nlogn)算法
- DP经典 之 CODE[VS] 1576 最长严格上升子序列 (O(n^2) 和 O(nlogn))
- HDU 5748 最长上升子序列的长度nlogn(固定尾部)
- HDU5748---(记录每个元素的 最长上升子序列 nlogn)
- 最长上升子序列(LIS)长度的O(nlogn)算法
- 最长非上升/非下降子序列(O(nlogn)非连续)
- 杭电ACM OJ 1025 Constructing Roads In JGShining's Kingdom 最长上升子序列 O(nlogn)算法详解+回溯暴力解决+动态规划dp优雅解决
- 蓝桥杯算法训练拦截导弹【最长上升子序列 & 最长非下降子序列nlogn 和 n^2】
- 最长上升子序列 nlogn