POJ1836:Alignment(LIS的应用)

题目链接:http://poj.org/problem?id=1836

题目要求:

给你n个数,判断最少去掉多少个数,从中间往左是递减的序列,往右是递增的序列
需注意的是中间可能为两个相同的值,如 1 2 3 3 2 1     输出为0

题目分析:

这题和UVA10534极其相似,因为刚做完,就果断粘贴复制了,唯一的不同是如果中间有两个士兵一样高是不用去掉的,(中间,仅限两个)。

我感觉这题是水过去的,我的代码只支持有一个最大值的情况,我的做法是先判断,如果求得最大值时这个点在队列当中的位置如果在边界,则直接结束。

否则,当在最大值时看之后有没有和最大值相同的值。~~~~怎么说呢,就是水过去的。

代码:

#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;
}
时间: 2024-10-14 07:01:12

POJ1836:Alignment(LIS的应用)的相关文章

POJ1836 Alignment 【LIS(二分)+枚举】

a1,a2,a3,a4,a5,a6...an 对ai求出a1到ai的lis,ai+1到an的lds 取所有ai对应的lis+lds最大值 输出n-lis-lds #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; int

poj1836——dp,最长上升子序列(lis)

poj1836——dp,最长上升子序列(lis) Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13767   Accepted: 4450 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight

SHUOJ A序列 &amp;&amp; POJ 1836 Alignment [动态规划 LIS]

A序列 发布时间: 2017年7月8日 21:16   最后更新: 2017年7月8日 22:29   时间限制: 1000ms   内存限制: 128M 描述 如果一个序列有奇数个正整数组成,不妨令此序列为a1,a2,a3,...,a2?k+1 (0<=k ),并且a1,a2...ak+1 是一个严格递增的序列,ak+1,ak+2,...,a2?k+1 ,是一个严格递减的序列,则称此序列是A序列. 比如1 2 5 4 3就是一个A序列. 现在Jazz有一个长度为n 的数组,他希望让你求出这个数

POJ 1836 Alignment 最长递增子序列(LIS)的变形

大致题意:给出一队士兵的身高,一开始不是按身高排序的.要求最少的人出列,使原序列的士兵的身高先递增后递减. 求递增和递减不难想到递增子序列,要求最少的人出列,也就是原队列的人要最多. 1 2 3 4 5 4 3 2 1 这个序列从左至右看前半部分是递增,从右至左看前半部分也是递增.所以我们先把从左只右和从右至左的LIS分别求出来. 如果结果是这样的: A[i]={1.86 1.86 1.30621 2 1.4 1 1.97 2.2} //原队列 a[i]={1 1 1 2 2 1 3 4} b[

poj 1836 Alignment (DP LIS)

Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13839   Accepted: 4478 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight line in front of the cap

POJ 1836 Alignment 枚举中间点双向求LIS

点击打开链接 Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13590   Accepted: 4375 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight line in front of

poj 1836 Alignment(dp,LIS)

链接:poj 1836 题意:士兵站成一行,求最少要多少的士兵出列, 使得每个士兵都能至少看到一个最边上的士兵 中间某个人能看到最边上的士兵的条件是: 该士兵的身高一定强大于他某一边(左边或右边)所有人的身高, 身高序列可以是: 1  2  3   4   5   4   3   2   1  或者 1   2   3   4   5   5   4   3   2   1 分析:要求最少出列数,就是留队士兵人数最大, 即左边的递增序列人数和右边的递减序列人数之和最大 因而可转化为求"最长升序子

poj 1836 Alignment 排队

poj   1836   Alignment http://poj.org/problem?id=1836 题意:有士兵n个,根据编号排为一列,但是身高不一,现在要求去掉几个人,使得剩下的每一个人可以向左或向右看到队头.问:至少去掉的士兵数. dp动态规划 之 双向LIS问题 1 /* 2 Problem: 1836 User: bibier 3 Memory: 712K Time: 63MS 4 Language: G++ Result: Accepted 5 */ 6 //动态规划 之 双向

POJ 1836-Alignment(DP/LIS变形)

Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13465   Accepted: 4336 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight line in front of the cap