这道题呢,思路还是很简单的
显然对于整个队列我们可以枚举中间点
然后呢,正反预处理最长上升子序列,就完事了
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,dp1[10005],dp2[10005],maxn,t[10005],cnt,q2[10005],q1[10005];
int find1(int x){
int l=1,r=cnt;
while(l<r){
int mid=(l+r)>>1;
if(q1[mid]<x)
l=mid+1;
else
r=mid;
}
return l;
}
int find2(int x){
int l=1,r=cnt;
while(l<r){
int mid=(l+r)>>1;
if(q2[mid]<x)
l=mid+1;
else
r=mid;
}
return l;
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&t[i]);
for(int i=1;i<=n;i++){
if(t[i]>q1[cnt])
q1[++cnt]=t[i];
else
for(int j=1;j<=cnt;j++)
if(q1[find1(t[i])]>=t[i]){
q1[find1(t[i])]=t[i];
break;
}
dp1[i]=cnt;
}
cnt=0;
for(int i=n;i>=1;i--){
if(t[i]>q2[cnt])
q2[++cnt]=t[i];
else
for(int j=1;j<=cnt;j++)
if(q2[find2(t[i])]>=t[i]){
q2[find2(t[i])]=t[i];
break;
}
dp2[i]=cnt;
}
/*for(int i=1;i<=n;i++)
printf("%d ",dp1[i]);
printf("\n");
for(int i=1;i<=n;i++)
printf("%d ",dp2[i]);
printf("\n");*/
for(int i=1;i<=n;i++)
maxn=max(maxn,dp1[i]+dp2[i]-1);
printf("%lld",n-maxn);
return 0;
}
经验与教训:
1.n2求子序列别忘了break!
2.二分别搞反方向了!