/*此题题意为任意去掉一个序列当中的元素后看这个序列是否满足almost sort 满足 yes,不满足 no*/
/*思路是典型的dp,通过将原序列和翻转顺序后的序列进行判断,判断原理是如果满足递增或递减 那么我们控制每次加1 那么 最终的总ans >= lis -1;*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxx = 1e5 + 5;
int N;//子序列的长度
int a[maxx], dp[maxx];//a为输入的序列
struct Stack {
int n, s[maxx];
void init() { n = 0;}
int find(int x){ return upper_bound(s, s + n, x) - s;} //第一个大于x值的位置
void insert(int p, int x) {
s[p] = x;
n = max(n, p + 1);
}
}S;
bool judge()
{
S.init();
int ans = 0;
for(int i = 1; i <= N; i++){
dp[i] = S.find(a[i]);//找到比当前元素大的第一个‘位置’即下标
S.insert(dp[i], a[i]);//将元素的值与当前大小顺序的下标对应,并持续更新所需目标数组的长度
ans = max(ans, dp[i] + 1);
}
return ans >= N - 1;//如果满足题目要求那么任意去掉一个元素后,剩余的每次加1最终恰好>=N-1
}
int main()
{
int cas;//多组输入
scanf("%d", &cas);
while(cas--){
scanf("%d", &N);
for(int i = 1; i <= N; i++) scanf("%d", &a[i]);
bool flag = judge();
reverse(a + 1, a + N + 1);//翻转函数包含a+1不包含a+n+1 这里的主要作用是将子序列反转后看是否满足任意去掉一个 是否满足从大到小或者从小到大
flag |= judge();
printf("%s\n", flag ? "YES" : "NO");
}
return 0;
}
hdu5532
最新推荐文章于 2019-07-25 13:43:45 发布