F - Almost Sorted Array HDU - 5532

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
题意:给你一个数组,判断在删除任意一个元素之后,该序列是否是递增序列或者递减序列。
普通思路:莽出所有的情况(反正我是没莽出来了)
dalao思路:LIS求最长上升子序列,和最长下降子序列。。。判断是否等于n or n-1,,,
咋的一看,好像很有道理的样子,然后我就敲了:
AC代码:

#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f//将近int类型最大数的一半,而且乘2不会爆int

int a[MAXN], dpa[MAXN], dpb[MAXN], b[MAXN];
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        memset(dpa, 0, sizeof(dpa));
        memset(dpb, 0, sizeof(dpb));
        int n, len = 1, cnt = 1;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
            b[n-i+1] = a[i];
        }
        dpa[1] = a[1];
        dpb[1] = b[1];
        for (int i = 2; i <= n; ++i)
        {
            if (a[i] >= dpa[len])
                dpa[++len] = a[i];
            else
            {
                int m = upper_bound(dpa + 1, dpa + 1 + len, a[i]) - dpa;
                dpa[m] = a[i];
            }
            if (b[i] >= dpb[cnt])
                dpb[++cnt] = b[i];
            else
            {
                int tem = upper_bound(dpb + 1, dpb + 1 + cnt, b[i]) - dpb;
                dpb[tem] = b[i];
            }
        }
        if (cnt == n || cnt == n - 1 || len == n || len == n - 1)
            puts("YES");
        else
            puts("NO");
    }
    return 0;
}

我wa了n次的代码:

#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f//将近int类型最大数的一半,而且乘2不会爆int

int a[MAXN], dpa[MAXN], dpb[MAXN], b[MAXN];
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        memset(dpa, 0, sizeof(dpa));
        memset(dpb, 0, sizeof(dpb));
        int n, len = 1, cnt = 1;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
            b[n-i+1] = a[i];
        }
        dpa[1] = a[1];
        dpb[1] = b[1];
        for (int i = 2; i <= n; ++i)
        {
            if (a[i] >= dpa[len])
                dpa[++len] = a[i];
            else
            {
                int m = lower_bound(dpa + 1, dpa + 1 + len, a[i]) - dpa;
                dpa[m] = a[i];
            }
            if (b[i] >= dpb[cnt])
                dpb[++cnt] = b[i];
            else
            {
                int tem = lower_bound(dpb + 1, dpb + 1 + cnt, b[i]) - dpb;
                dpb[tem] = b[i];
            }
        }
        cout << len << ' ' << cnt << '\n';
        if (cnt == n || cnt == n - 1 || len == n || len == n - 1)
            puts("YES");
        else
            puts("NO");
    }
    return 0;
}

不得不说这两份代码就只有:lower_bound 和 upper_bound 的区别。。。。我之前打的LIS全是用lower_bound的,,所以,我在疯狂的wa了之后,就去搜题解了,,,然后一改, 就绿了,我。。。。。那么lower_bound 和 upper_bound 的区别到底在哪里呢?!
敬请看博客:lower_bound 和 upper_bound的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值