贪心。
从A的末端插到B的中间,再从B的中间插到C的末端。
可以证明,A->B的过程中,插到中间的左边,和右边的结果是一样的
又因为A->B先插入的,B->C先取出。B->C若长度为偶数可以从中间两个中取较小的。
所以只考虑末尾的两个数即可,使用vector进行插入和删除操作,由于只对末尾进行操作,故复杂度为O(n)
最后检查是否为non-decreasing即可
代码如下
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<iomanip>
#include<cstring>
#include<climits>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define fo(i,a) for(int i=0;i<a;++i)
typedef long long ll;
const int N = 2e5 + 5;
typedef vector<int> vec;
int a[N];
int main() {
int T;
cin >> T;
int n;
while (T--) {
cin >> n;
vec b, c;
bool flag = 1;
go(i, 1, n) {
cin >> a[i];
}
for (int i = n; i >= 1; --i) {
int len = n - i;
b.push_back(a[i]);//从尾部先出
//可以证明,无论是插左边还是插右边,其实都是等价的
}
int l = n;
while (l) {
if (l % 2 == 0) {
if (b[l - 1] < b[l - 2]) {
c.push_back(b[l - 1]);
b.pop_back();
}
else {
c.push_back(b[l - 2]);
b.erase(b.begin() + l - 2);
}
}
else {
c.push_back(b[l - 1]);
b.pop_back();
}
--l;
}
for (int i = 1; i < n; ++i) {
if (c[i] < c[i - 1]) {
cout << "NO" << endl;
flag = 0;
break;
}
}
if (flag == 1)
cout << "YES" << endl;
}
}