1. 程式人生 > >HDU - 5532(Almost Sorted Array)最長上升子序列

HDU - 5532(Almost Sorted Array)最長上升子序列

題意:

給出一個長度為n的數列,問刪除一個數後,剩下的數列能否成為一個非遞增或非遞減數列,可以輸出“YES”,否則輸出“NO”。

題解:

使用兩次最長上升子序列(LIS)。(抄了抄板子)

第一次,求非遞減序列的最大長度,不用做任何處理。

第二次,把原陣列取相反數(乘上一個-1),再進行一次LIS即可。

取兩次的最大值,如果大於等於n-1輸出“YES”。

附LIS(二分)程式碼:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#include <iomanip>
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
#define clr(str,x) memset(str,x,sizeof(str))
#define INF 0x3f3f3f3f
#define maxn 100010

typedef long long int ll;
using namespace std;
int a[maxn],b[maxn];
int Search(int num,int low,int high)
{
    int mid;
    while(low<=high)
    {
        mid=(low+high)/2;
        if(num>=b[mid])
            low=mid+1;
        else
            high=mid-1;
    }
    return low;
}
int LIS(int n)
{
    memset(b,0,sizeof(b));
    b[1]=a[1];
    int len=1,pos;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>=b[len])
        {
            len++;
            b[len]=a[i];
        }
        else
        {
            pos=Search(a[i],1,len);
            b[pos]=a[i];
           // printf("pos=%d\n",pos);
        }
    }
    return len;
}
int main()
{
    //FRER()
    //FREW()
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        memset(a,0,sizeof(a));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        int ans1=LIS(n);
        for(int i=1;i<=n;i++)
        {
            a[i]=-a[i];
        }
        int ans2=LIS(n);
        int ans=max(ans1,ans2);
        if(ans>=n-1)
            printf("YES\n");
        else
            printf("NO\n");

    }
    return 0;
}