题意:给出一个数组,相邻两个数字满足 A i < A i − 1 A_i < A_{i-1} Ai<Ai−1,就可以删除其中一个数字。问是否存在一种删除方案,使数组中只剩下一个元素。
思路:
栈模拟
用栈来模拟数字在数组中的 先后顺序(先后入栈)和贪心决策(是否入栈,是否出栈)
设要入栈元素a,栈顶元素b
1.如果栈为空,直接入栈。
2.如果 a < b a < b a<b,直接入栈。
3.如果 a > b a > b a>b,就满足删除的条件,到了贪心决策的问题了。
(1).如果此时栈中只有一个元素,我们优先选择较小的 b b b。:
分区间讨论,假如在a的右边有 [ a , n ] [a,n] [a,n]中的元素,那留下 a , b a,b a,b都行,假如在 a a a的右边有 [ b , a ] [b,a] [b,a]中的元素,只能留下 b b b,假如在 a a a的右边有 [ 1 , b ] [1,b] [1,b]中的元素,那么留下 a , b a,b a,b都不行, b b b的优先级更高。
(2).如果栈中有多个元素,我们要尽量的删除较多的元素。
那我们也可以分区间讨论,栈中元素所在区间,和留下 a , b a,b a,b,哪个可能删除的元素更多。讨论结果就是留下 a a a,循环删除栈中的元素,直到栈中只剩下一个元素或不满足删除条件。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5+10;
const int inf = 0x7ffffff;
int f[][2] = {
1, 0, 0, 1, -1, 0, 0, -1}, n, m;
int s[N];
int read() {
int x = 0; int f = 1; char s = getchar();
while(s < '0' || s > '9') {
if(s == '-') f = -1; s = getchar();}
while(s >= '0' && s <= '9') {
x = (x << 3) + (x << 1) + s - 48; s = getchar();}
return x * f;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int t;
t = read();
while(t--) {
stack<int> T;
int n, f, mx = 0, mi = 0;
n = read();
for(int i=1; i<=n; i++) {
s[i] = read();
if(s[i] == 1) f = i;
}
for(int i=1; i<=n; i++) {
//一个一个元素进行决策。
if(T.empty()) T.push(s[i]);//空
else if(s[i] < T.top()) T.push(s[i]);//不满足删除条件
else {
//满足删除条件
if(T.size() == 1) continue;//只有一个元素
else T.push(s[i]);
while(1) {
//贪心决策
int a = T.top(); T.pop();
int b = T.top(); T.pop();
if(a > b) {
//留a还是留b
if(T.size() > 0) T.push(a);
else T.push(b);
}
else {
//不满足删除条件了
T.push(b); T.push(a);
break;
}
if(T.size() == 1) break;//只剩下一个元素
}
}
}
if(T.size() == 1) puts("YES");
else puts("NO");
}
return 0;
}
按照上面的模拟,我们可以想想第一个元素是不是一直没有被删除。在对最后一个元素进行决策时,如果最后一个元素会和第一个元素相遇,且满足删除条件的话( A 1 < A n A_1 < A_n A1<An),就会留下第一个元素。如果在中间的时候就存在不满足删除条件的情况,我们按这样排一下序。
第 一 个 元 素 A 1 , 对 最 后 一 个 元 素 不 满 足 删 除 条 件 的 元 素 A i , 最 后 一 个 元 素 A n 第一个元素A_1,对最后一个元素不满足删除条件的元素A_i,最后一个元素A_n 第一个元素A1,对最后一个元素不满足删除条件的元素Ai,最后一个元素An
可以推出 A i > A n A_i > A_n Ai>An,且因为在对 A i A_i Ai这个元素决策的时候,留下了它,说明 A 1 > A i A_1 > A_i A1>Ai。这里已经有结论的影子了,具体证明我也弄不出来。
结论
只需要比较第一和最后一个数字的大小即可。
S 1 > S n , N o S 1 < S n , Y E S S_1 > S_n,~~~No~~~~~~~~~~~S_1 < S_n,~~~YES S1>Sn, No S1<Sn, YES
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5+10;
const int inf = 0x7ffffff;
int f[][2] = {
1, 0, 0, 1, -1, 0, 0, -1}, n, m;
int s[N];
int read() {
int x = 0; int f = 1; char s = getchar();
while(s < '0' || s > '9') {
if(s == '-') f = -1; s = getchar();}
while(s >= '0' && s <= '9') {
x = (x << 3) + (x << 1) + s - 48; s = getchar();}
return x * f;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int t;
t = read();
while(t--) {
int n, f, mx = 0, mi = 0;
n = read();
for(int i=1; i<=n; i++) {
s[i] = read();
}
if(s[n] < s[1]) printf("NO\n");
else printf("YES\n");
}
return 0;
}