题意:
给出一个长度为n的数列,问删除一个数后,剩下的数列能否成为一个非递增或非递减数列,可以输出“YES”,否则输出“NO”。
题解:
使用两次最长上升子序列(LIS)。(抄了抄板子)
第一次,求非递减序列的最大长度,不用做任何处理。
第二次,把原数组取相反数(乘上一个-1),再进行一次LIS即可。
取两次的最大值,如果大于等于n-1输出“YES”。
附LIS(二分)代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#include <iomanip>
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
#define clr(str,x) memset(str,x,sizeof(str))
#define INF 0x3f3f3f3f
#define maxn 100010
typedef long long int ll;
using namespace std;
int a[maxn],b[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 LIS(int n)
{
memset(b,0,sizeof(b));
b[1]=a[1];
int len=1,pos;
for(int i=2;i<=n;i++)
{
if(a[i]>=b[len])
{
len++;
b[len]=a[i];
}
else
{
pos=Search(a[i],1,len);
b[pos]=a[i];
// printf("pos=%d\n",pos);
}
}
return len;
}
int main()
{
//FRER()
//FREW()
int T,n;
scanf("%d",&T);
while(T--)
{
memset(a,0,sizeof(a));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int ans1=LIS(n);
for(int i=1;i<=n;i++)
{
a[i]=-a[i];
}
int ans2=LIS(n);
int ans=max(ans1,ans2);
if(ans>=n-1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}