题目:给你一个序列,问你,这个序列只减少一个元素,减少之后是否为不上升序列或者不下降序列。
思路:直接对序列求最长不下降和不上升子序列,如果这个子序列的长度为n-1或者n的话,就符合题目条件。
最长不下降子序列和最长不上升子序列:这里使用数据结构的方法求最长不上升(下降)子序列的长度。就是另外构造一个数组 f[] ,这个数组表示的意思是:f [ i ] 表示的是长度为 i 的子序列的最小(最大值),因为,同样长度的子序列,最后一个数字最小或最大的时候,更方便往后面放数字。这个时候可能会说就算我的这个数字足够小或者足够大,如果位置不对,那么以他为结尾的序列长度也不能是最长的。至于这个问题,其实,我们更新的是 f[] ,每次我们都从头到尾地扫 f[] ,更新这个数组,就不会出现那个问题了。
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<vector> 7 #include<string> 8 #include<queue> 9 #include<map> 10 #include<stack> 11 #include<set> 12 #define ll long long 13 #define maxn 100010 14 #define PI acos(-1.0) //圆周率 15 const int mod=1e9+7; 16 using namespace std; 17 int num[maxn]; 18 int f[maxn]; 19 int n; 20 int main() 21 { 22 int T; 23 scanf("%d",&T); 24 while(T--) 25 { 26 memset(f,0,sizeof(f)); 27 memset(num,0,sizeof(num)); 28 29 scanf("%d",&n); 30 for(int i=0;i<n;i++) scanf("%d",&num[i]); 31 32 int len=1; 33 f[0]=num[0]; 34 for(int i=1;i<n;i++) 35 { 36 if(num[i]>=f[len-1]) f[len++]=num[i]; 37 else 38 { 39 int cnt=upper_bound(f,f+len,num[i])-f; 40 f[cnt]=num[i]; 41 } 42 } 43 44 if(len==n-1||len==n) 45 { 46 printf("YES "); 47 continue; 48 } 49 50 len=1; 51 memset(f,0,sizeof(f)); 52 f[0]=num[n-1]; 53 for(int i=n-2;i>=0;i--) 54 { 55 if(num[i]>=f[len-1]) f[len++]=num[i]; 56 else 57 { 58 int cnt=upper_bound(f,f+len,num[i])-f; 59 f[cnt]=num[i]; 60 } 61 } 62 63 if(len==n-1||len==n) printf("YES "); 64 else printf("NO "); 65 } 66 67 return 0; 68 }