HDU 5532 Almost Sorted Array (LIS)

70 篇文章 0 订阅

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 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 .

1T2000
2n105
1ai105
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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值