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
#include
#include
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
#include
#include
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的区别