poj 3093 最长上升子序列
单调栈的优化的过程,需要二分的做法,二分的做法是可以使用low_bound,这个函数的作用是去前闭后开的区间中,第一个大于等于val的值的位置,这个函数不错
不使用stl的代码,感觉我的二分写的好烂
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> const int maxn=100008; using namespace std; int n,a[maxn],top[maxn],cnt=0; //二分写的不好 void ef(int s,int value,int t) { int mid=(s+t)/2; if(s>t) return; if(mid<1) return; if(value<top[mid]&&value>top[mid-1]) { top[mid]=value; return; } if(value>top[mid]) ef(mid+1,value,t); if(value<top[mid-1]) ef(s,value,mid-1); } int main() { while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); memset(top,0,sizeof(top)); cnt=1; for(int i=1;i<=n;i++) scanf("%d",&a[i]); top[1]=a[1]; for(int i=2;i<=n;i++) { if(a[i]>top[cnt]) { cnt++; top[cnt]=a[i]; } else { if(a[i]<top[1]) top[1]=a[i];//先判断一个的情况,这个很重要 else ef(1,a[i],cnt); } } printf("%d\n",cnt); } } /** 6 5 2 1 4 5 3 3 1 1 1 4 4 3 2 1 **/
使用stl的部分
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> const int maxn=100008; using namespace std; int n,a[maxn],top[maxn],cnt=0; int main() { while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); memset(top,0,sizeof(top)); cnt=1; for(int i=1;i<=n;i++) scanf("%d",&a[i]); top[1]=a[1]; for(int i=2;i<=n;i++) { if(a[i]>top[cnt]) { cnt++; top[cnt]=a[i]; } else { if(a[i]<top[cnt]&&a[i]>top[cnt-1]) top[cnt]=a[i]; else { int pos=lower_bound(top+1,top+cnt,a[i])-top; top[pos]=a[i]; } } } printf("%d\n",cnt); } } /** 6 5 2 1 4 5 3 3 1 1 1 4 4 3 2 1 **/