最长不下降子序列Lis问题
复习代码速记用,不涉及原理。不可用于初学。
定义
是一种问题类型,隶属于动态规划。指一个序列中最长的单调递增的子序列(可以不连续)
解法
朴素(N2)
每一次在他的前面找一个比他小的数,和他进行一次连接。取连接数量较大的值。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cstring> #include <cmath> using namespace std; const int maxn = 103, INF = 0x7f7f7f7f; int a[maxn], f[maxn]; int n,ans = -INF; int main() { scanf("%d", &n); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); f[i] = 1; } for(int i=1; i<=n; i++) for(int j=1; j<i; j++) if(a[j] < a[i]) f[i] = max(f[i], f[j]+1); for(int i=1; i<=n; i++) ans = max(ans, f[i]); printf("%d\n", ans); return 0; }
进步优化(NlogN)
其中有一个栈的思想。
第一个元素直接入栈。对于之后的元素,如果大于栈顶就入栈,否则二分查找一个比这个值刚好大的数字替换掉。
#include<iostream> #include<algorithm> using namespace std; int a[1001]; int top=0; int main(){ int n; int x; scanf("%d%d",&n,&x); a[++top]=x; for(int i=2;i<=n;i++){ scanf("%d",&x); if(x>a[top]){ a[++top]=x; } else{ int p=upper_bound(a+1,a+top+1,x)-a; a[p]=x; } } cout<<top; }
高端写法(树状数组)
等待引入…
树状数组