8
186 186 150 200 160 130 197 220
4
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define INF 1<<30 using namespace std; int N,res=INF,a[105],b[105],dp[105],f[105],l,r; int longest(int k){ fill(dp,dp+N,INF); for(int i=1;i<=k;i++){ *lower_bound(dp,dp+N,a[i])=a[i]; if(i==k) l=lower_bound(dp,dp+N,INF)-dp; } // printf("k=%d l=%d ",k,l); fill(dp,dp+N,INF); for(int i=1;i<=N-k+1;i++){ *lower_bound(dp,dp+N,b[i])=b[i]; if(i==N-k+1) r=lower_bound(dp,dp+N,INF)-dp; } // printf("r=%d\n",r); if(r==1||l==1) return -1; return l+r-1; } int main(){ // freopen("01.txt","r",stdin); scanf("%d",&N); for(int i=1;i<=N;i++) scanf("%d",&a[i]); for(int i=1;i<=N;i++) b[i]=a[N-i+1]; // for(int i=1;i<=N;i++) printf("%d ",b[i]); for(int i=1;i<=N;i++){ int k=longest(i); if(k==-1) k=INF; else k=N-k; res=min(res,k); } if(res==INF) res=0; printf("%d\n",res); return 0; }直接顺序读入a数组,再逆序复制一份到b,枚举中间点,过一下最长上升子序列,
记录当中间点推入时的序列长度,得到最小值;
其实可以不用逆序复制,为了不浪费时间,采用了O(nlogn)的lower_bound;
看了下题解发现本来就是上升或下降(及没有答案时)要输出0;
原文:http://www.cnblogs.com/radiumlrb/p/5782557.html