说是第二天,但我昨天太懒没写,今天一起补上吧。
PART ONE : DP复习一
分析:其实这道题本身并不难,就是正反跑一遍最大上升子序列,求一个和总长度最小的差值就行了,但是这道题有一组神奇的数据导致n^3的方法过不去,我正好又不会写二分,于是......
于是我想趁机说一下二分的有关事项,代码在下面,但是对于可以二分的题我们可以尝试使用lower_bound和upper_bound,我暂时只会用单调上升的,下降的它会返回一些奇奇怪怪的数,他们的功能是这样的,如果我们查找的数在序列中没有,那么他们两个的作用都是返回最后一个小于所查数的位置(注意是位置,在最后要减去数组位置,从1开始的数组要减a+1),如果所查数存在,lower_bound作用不变,upper_bound变为返回位置最大的所查数的位置,比较麻烦,所以以后能手写二分还是手写吧.......
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int N=1e6+10; 5 using namespace std; 6 int erfen(int *a,int r,int x){ 7 int l=1,mid; 8 while(l<=r){ 9 mid=(l+r)>>1; 10 if(a[mid]<=x) l=mid+1; 11 else r=mid-1; 12 } 13 return l; 14 } 15 int a[N],b[N],c[N],sum,ans1,ans2; 16 int main(){ 17 //freopen("a.in","r",stdin); 18 int n; 19 scanf("%d",&n); 20 for(int i=1;i<=n;++i){ 21 scanf("%d",&a[i]); 22 b[n-i+1]=a[i]; 23 } 24 c[1]=a[1];sum=1; 25 for(int i=2;i<=n;++i){ 26 if(a[i]>=c[sum]) c[++sum]=a[i]; 27 else if(a[i]<c[sum]){ 28 int t=erfen(c,sum,a[i]); 29 c[t]=a[i]; 30 } 31 } 32 ans1=n-sum; 33 memset(c,0,sizeof(c));sum=1;c[1]=b[1]; 34 for(int i=2;i<=n;++i){ 35 //for(int j=1;j<=sum;++j) printf("%d ",c[j]); puts(""); 36 if(b[i]>=c[sum]) c[++sum]=b[i]; 37 else if(b[i]<c[sum]){ 38 int t=erfen(c,sum,b[i]); 39 c[t]=b[i]; 40 } 41 } 42 ans2=n-sum; 43 printf("%d\n",min(ans1,ans2)); 44 return 0; 45 }