Almost Sorted Array(nlogn的LIS)

Almost Sorted Array(nlogn的LIS)

We are all familiar with sorting algorithms: quick sort, merge sort, heap sort, insertion sort, selection sort, bubble sort, etc. But sometimes it is an overkill to use these algorithms for an almost sorted array. We say an array is sorted if its elements are in non-decreasing order or non-increasing order. We say an array is almost sorted if we can remove exactly one element from it, and the remaining array is sorted. Now you are given an array a1, a2, . . . , an, is it almost sorted?

Input

The first line contains an integer T indicating the total number of test cases. Each test case starts with an integer n in one line, then one line with n integers a1, a2, . . . , an.

• 1 ≤ T ≤ 2000

• 2 ≤ n ≤ 105

• 1 ≤ ai ≤ 105

• There are at most 20 test cases with n > 1000.

Output

For each test case, please output ‘YES’ if it is almost sorted. Otherwise, output ‘NO’ (both without quotes).

Sample Input

3

3

2 1 7

3

3 2 1

5

3 1 4 1 5

Sample Output

YES

YES

NO

题意

定义:如果一个数组去掉一个数后剩下的数是不上升数组或不下降数组,那么这个数组就是Almost Sorted Array,判断并给到的数组是否为Almost Sorted Array

思路

一开始想到模拟,枚举删去一个数字,再枚举剩下的数字,若不符合就退出。这样妥妥的超时。

后来又用了动态规划求LIS,复杂度O(n2)超时。

这样就要用复杂度为O(nlogn)的方法求LIS了,对于判断不上升数组,只要把原数组调个头再判断它是否不下降。

注意

因为是不下降而不是上升,所以用的是upper_bound而不是low_bound

代码

#include
#include
#include
#include
const int maxN=100005;
using namespace std;
int a[maxN],b[maxN];
/*int Find(int l,int r,int val)
{
    int mid;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(s[mid]>val)
        r=mid-1;
        else
        l=mid+1;
    }
    return l;
}*/
int LIS(int n)
{
    int lis[maxN];
    lis[1]=a[1];
    int len=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>=lis[len])
            lis[++len]=a[i];
        else
        {
            int pos=upper_bound(lis,lis+len,a[i])-lis;
            lis[pos]=a[i];
        }
    }
    return len;
}
int LIS2(int n)
{
    int lis[maxN];
    lis[1]=b[1];
    int len=1;
    for(int i=2;i<=n;i++)
    {
        if(b[i]>=lis[len])
            lis[++len]=b[i];
        else
        {
            int pos=upper_bound(lis,lis+len,b[i])-lis;
            lis[pos]=b[i];
        }
    }
    return len;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[n-i+1]=a[i];
        }
        if(LIS(n)>=n-1||LIS2(n)>=n-1)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

 

你可能感兴趣的:(算法)