最长不降子序列,O(n^2)算法能超时超到明年
需要o(nlogn)算法(CMI)
这个问题利用到了辅助数组d[i],这里姑且称它为栈,因为对该
数组的操作像是栈的操作,d[i]表示长度为i的不降子序列中最小
的最后元素,最后栈的长度就是最长不降子序列的长度
当循环到a[i]的时候和栈顶元素s比较,如果s<=a[i],就是说a
[i]比最长的不降子序列的最小的那个元素大或等于,那么把a
[i]放到栈顶,子序列也就加了1
如果s>a[i]则在栈中找最大的j使得d[j]<=a[i],然后将j+1替换
为a[i],因为栈中的元素都是单调递增的(随便想一下就知道),
所以可以用二分求上限求得,这样的查找的时间复杂度就是
o(logn),总的复杂度就是o(nlogn)
重点就是二分求上限,LRJ的小白书上就有
1 //288 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 const int maxn = 30005; 8 int d[maxn],a[maxn],cnt = 0; 9 int up_search(int l,int r,int val) 10 { 11 while(l<r) 12 { 13 int m = (l+r)>>1; 14 if(d[m]<=val)l = m+1; 15 else r = m; 16 //printf("%d\n",cnt++); 17 } 18 return l; 19 } 20 int main() 21 { 22 //freopen("in.txt","r",stdin); 23 int n; 24 cin>>n; 25 for(int i = 1;i<=n;++i)scanf("%d",a+i); 26 int r = 0; 27 for(int i = 1;i<=n;++i) 28 if(!r)d[++r] = a[i]; 29 else 30 { 31 if(a[i]>=d[r])d[++r] = a[i]; 32 else d[up_search(1,r,a[i])] = a[i]; 33 } 34 printf("%d\n",r); 35 return 0; 36 }
时间: 2024-12-24 01:30:24