题目链接:http://poj.org/problem?id=1836
题目要求:
给你n个数,判断最少去掉多少个数,从中间往左是递减的序列,往右是递增的序列
需注意的是中间可能为两个相同的值,如 1 2 3 3 2 1 输出为0
题目分析:
队列不是对称的,并且如果中间有两个士兵一样高是不用去掉的,(中间,仅限两个)。
我感觉这题是水过去的,我的代码只支持有一个最大值的情况,我的做法是先判断,如果求得最大值时这个点在队列当中的位置如果在边界,则直接结束。
否则,当在最大值时看之后有没有和最大值相同的值。~~~~怎么说呢,就是水过去的。但这题n的值为1000,所以这题可以枚举。
基本操作方法:
对士兵的身高数组逐一进行枚举,枚举到的k值作为蓝色士兵,k+1值作为红色士兵,以这两个士兵分别作为最长不降子序列L1的终点和最长不升子序列L2的起点,即作为整个队列的分界点。
正确的写法:(枚举)
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
int n,sum,len,l2;
double a[10002],d[10002],w[10002];
int er(double q[],int l,int r,double key)//好好研究二分
{
int mid;
while(l<=r)
{
mid=(l+r)/2;
if(q[mid]==key)
{
return mid;
}
else if(q[mid]>key)
{
r=mid-1;
}
else l=mid+1;
}
return l;
}
int er2(double q[],int l,int r,double key)//好好研究二分
{
int mid;
while(l<=r)
{
mid=(l+r)/2;
if(q[mid]==key)
{
return mid;
}
else if(q[mid]>key)
{
l=mid+1;
}
else r=mid-1;
}
return l;
}
int main()
{
int we,wei;
while(scanf("%d",&n)!=EOF)
{
for(int i=1; i<=n; i++)
{
scanf("%lf",&a[i]);
}
sum=1;
len=1;
d[len]=a[1];
for(int i=2; i<=n; i++)
{
if(a[i]>d[len])
{
d[++len]=a[i];
l2=1;
w[l2]=a[i+1];
for(int j=i+2; j<=n; j++)
{
if(a[j]<w[l2])
{
w[++l2]=a[j];
}
else
{
wei=er2(w,1,l2,a[j]);
w[wei]=a[j];
}
}
sum=max(sum,max(l2,len));
if(i<n&&(a[i]>a[i+1]||l2>1))
sum=max(sum,(l2+len));
//printf("sum==%d\n",sum);
}
else
{
we=er(d,1,len,a[i]);
d[we]=a[i];
if(len<=1) continue;
l2=1;
w[l2]=a[i+1];
for(int j=i+2; j<=n; j++)
{
if(a[j]<w[l2])
{
w[++l2]=a[j];
}
else
{
wei=er2(w,1,l2,a[j]);
w[wei]=a[j];
}
}
sum=max(sum,max(l2,we));
if(i<n&&(a[i]>a[i+1]||l2>1))
sum=max(sum,(l2+we));
//printf("sum==%d\n",sum);
}
}
printf("%d\n",n-sum);
}
return 0;
}
水的代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#define eps 1e-9
using namespace std;
int n,ad[10002],ad2[10002],sum,len,l2;
double a[10002],d[10002],w[10002];
int er(double q[],int l,int r,double key)//好好研究二分
{
int mid;
while(l<=r)
{
mid=(l+r)/2;
if(q[mid]==key)
{
return mid;
}
else if(q[mid]>key)
{
r=mid-1;
}
else l=mid+1;
}
return l;
}
int main()
{
int we;
while(scanf("%d",&n)!=EOF)
{
for(int i=1; i<=n; i++)
{
scanf("%lf",&a[i]);
}
sum=1;
len=1;
d[len]=a[1];
ad[1]=1;
for(int i=2; i<=n; i++)
{
if(a[i]>d[len])
{
d[++len]=a[i];
ad[i]=len;
}
else
{
we=er(d,1,len,a[i]);
d[we]=a[i];
ad[i]=we;
}
}
l2=1;
w[l2]=a[n];
ad2[n]=1;
for(int i=n-1; i>=1; i--)
{
if(a[i]>w[l2])
{
w[++l2]=a[i];
ad2[i]=l2;
}
else
{
we=er(w,1,l2,a[i]);
w[we]=a[i];
ad2[i]=we;
}
}
int key=1;
for(int i=1;i<=n;i++)
{
if(sum<(ad[i]+ad2[i]-1))
{
sum=ad[i]+ad2[i]-1;
key=i;
}
}
if(ad[key]==1||ad2[key]==1)
{
printf("%d\n",n-sum);
continue;
}
int F=0;
if(ad[key]==ad2[key])
{
for(int i=n;i>key;i--)
{
if(a[i]==a[key])
{
F=1;
printf("%d\n",n-sum-1);
break;
}
}
}
if(F==1)
continue;
if(a[key-1]==a[key]||a[key]==a[key+1])
{
printf("%d\n",n-sum-1);
}
else printf("%d\n",n-sum);
}
return 0;
}