Almost Sorted Array
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3333 Accepted Submission(s): 836
Problem Description
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 a
1
,a
2
,…,a
n![]()
, is it almost sorted?
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 a
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
a
1
,a
2
,…,a
n![]()
.
1≤T≤2000
2≤n≤10
5![]()
1≤a
i
≤10
5![]()
There are at most 20 test cases with n>1000
.
1≤T≤2000
2≤n≤10
1≤a
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
Source
题意:给定一组序列,问去掉其中某一个或不去掉剩下的序列是否是严格不下降或不上升序列。
思路:一开始想采用遍历与周围两个比较的方法,但是情况考虑不全,后来想到用LIS,但是一开始T了,后来发现LIS有一种o(nlogn)的实现方式很巧妙。开两个数组,一个数组是原序列,另一个数组保存到该下标前数组中最大的数,对之后的位置,若原序列中的数大于该位置的数,则直接放进数组中,否则找到数组中第一个大于该数的位置,将该位置的数改为原序列中的数。最后这个数组的长度即为LIC的长度。相当于开了无数个数组存放,但因为只改变长度,所以增加什么数字不会对LIS此时的长度有所影响,很巧妙。
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <stdio.h>
using namespace std;
const int MAXN = 500010;
int a[MAXN],b[MAXN],c[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 dp(int n){
int i,len,pos;
b[1]=a[1];
len=1;
for(i=2;i<=n;i++){
if(a[i]>=b[len]){
len=len+1;
b[len]=a[i];
}
else{
pos=Search(a[i],1,len);
b[pos]=a[i];
}
}
return len;
}
int dp1(int n){
int i,len,pos;
b[1]=c[1];
len=1;
for(i=2;i<=n;i++){
if(c[i]>=b[len]){
len=len+1;
b[len]=c[i];
}
else{
pos=Search(c[i],1,len);
b[pos]=c[i];
}
}
return len;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
c[n-i+1]=a[i];
}
int k1=dp(n);
int k2=dp1(n);
if(k1>=n-1||k2>=n-1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}