九度1500

题目意思很简单,算是一个最长公共子序列的加强版把,可以这么认为把。如果让你排成单调向上的一排,相信大家都会做,那么如果是山峰那样的,其实我也需要从前往后,从后往前做一下最长上升自序列,然后枚举每一个点作为最高点,取一个最优的即可,n比较大的时候需要nlogn算法,一般是二分,前几天看到也可以用树状数组做。

附1500代码如下

#include<stdio.h>
#include<string.h>
int a[1000001];
int dp1[100001];
int dp2[100001];
int lr[1000001];
int rl[1000001];
int main()
{
	int n;
	int i,j;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=1;i<=n;i++)
			scanf("%d",a+i);
		dp1[1]=a[1];
		lr[1]=1;
		int l,r;
		int l1=1;
		
		for(i=2;i<=n;i++)
		{
			l=0,r=l1;
			while(l<=r)
			{
				int mid=l+(r-l)/2;
				if(a[i]<=dp1[mid])
					r=mid-1;
				else 
					l=mid+1;
			}
			dp1[l]=a[i];	
			if(l>l1)
				l1++;
			lr[i]=l1;

		}
		int l2=1;
		dp2[1]=a[n];
		rl[n]=1;
		int ll,rr;
		
		for(i=n-1;i>=1;i--)
		{
			ll=0,rr=l2;
			while(ll<=rr)
			{
				int mid=ll+(rr-ll)/2;
				if(a[i]<=dp2[mid])
					rr=mid-1;
				else 
					ll=mid+1;
			}
			dp2[ll]=a[i];
			if(ll>l2)
				l2++;
			rl[i]=l2;
		}
		int ans=-1;
		for(i=1;i<=n;i++)
			if(ans<lr[i]+rl[i]-1)
				ans=lr[i]+rl[i]-1;
		printf("%d\n",n-ans);

	}
	return 0;
}


		


你可能感兴趣的:(优化,动态规划)