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

版权声明:SDKD-Vici__ https://blog.csdn.net/Vici__/article/details/83478826

题意:

给出一个长度为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;
}

猜你喜欢

转载自blog.csdn.net/Vici__/article/details/83478826