题目大意
给出一个
n
n
n个数的数列
a
1
,
a
2
,
⋯
,
a
n
a_1,a_2,\cdots,a_n
a1,a2,⋯,an。
定义删除操作为:若
a
i
<
a
i
+
1
a_i<a_{i+1}
ai<ai+1,则可以删除
a
i
a_i
ai或者
a
i
+
1
a_{i+1}
ai+1,整个数列的顺序保持不变。
问是否存在一种方案,使得最后只剩下一个数。
时间限制
1s
数据范围
n ≤ 3 × 1 0 5 n \le 3\times 10^5 n≤3×105
题解
考虑这个删除的过程,显然最开始是用
a
1
a_1
a1x向右来删除,
如果遇到一个比
a
1
a_1
a1小的数怎么办呢?
不妨记这个数为
a
i
a_i
ai,那么就可以用
a
i
a_i
ai往后删除,直到找到一个比
a
1
a_1
a1大的数。
于是,按照这个思路,从左到右维护一个最小值,
每次用这个当前最小值来删除,直到出现比它更小的。
这个过程非常类似单调栈。
Code
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#define G getchar
#define ll long long
using namespace std;
int read()
{
char ch;
for(ch = G();(ch < '0' || ch > '9') && ch != '-';ch = G());
int n = 0 , w;
if (ch == '-')
{
w = -1;
ch = G();
} else w = 1;
for(;'0' <= ch && ch <= '9';ch = G())n = (n<<1)+(n<<3)+ch-48;
return n * w;
}
const int N = 300005;
int n , a[N] , mi[N] , top;
bool ans , bz;
int main()
{
//freopen("b.in","r",stdin);
//freopen("l.out","w",stdout);
for (int T = read() ; T ; T--)
{
n = read();
for (int i = 1 ; i <= n ; i++)
a[i] = read();
ans = 1;
top = 1;
mi[1] = a[1];
for (int i = 2 ; i <= n ; i ++)
if (a[i] < mi[top])
{
top++;
mi[top] = a[i];
if (a[i - 1] < mi[top - 1])
{
ans = 0;
break;
}
}
if (ans && (a[n] > a[1])) puts("YES"); else puts("NO");
}
return 0;
}