题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=5532
题意
给一个序列,可以去掉其中一个元素,判断序列能否在去掉某个元素后成为一个有序序列
思路
因为序列可以不严格单调增/减,先单独考虑单调增的情况,减相同处理
设f(i)为以i结尾的不严格单调递增的序列长度,g(i)为以i开头的不严格单调递减的序列长度,比如如下序列a[]:
3,4,2,5,6
f[1] = 1, f[2] = 2, f[3] = 1, f[4] = 2, f[5] = 3;
g[1] = 2, g[2] = 1, g[3] = 3, g[4] = 2, g[5] = 1;
假如我们有了f[]和g[]了,则只需要枚举要去掉的元素i,使得:f[i - 1] + g[i + 1] == n - 1 && a[i + 1] >= a[i - 1]即可,时间复杂度为O(n)
则只需要得到f[]和g[]了,不难发现只需要数组分别往后和往前滚一遍就可以递推得到f[]和g[]
单调减的时候相同处理
以及有些细节需要处理一下
代码
代码比较臃肿= =
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl
const int maxn = 100000 + 5;
const int INF = 100000 + 5;
int a[maxn], f[maxn], g[maxn];
int n;
int main() {
int T;
scan(T);
while (T--) {
scan(n);
memset(f, 0, sizeof(f));
memset(g, 0, sizeof(g));
a[0] = 0;
a[n + 1] = INF;
for (int i = 1; i <= n; i++) {
scan(a[i]);
if (a[i] >= a[i - 1]) f[i] = f[i - 1] + 1;
else f[i] = 1;
}
for (int i = n; i >= 1; i--) {
if (a[i] <= a[i + 1]) g[i] = g[i + 1] + 1;
else g[i] = 1;
}
if (n == 2) {
puts("YES");
continue;
}
if (g[1] == n || f[n] == n) {
puts("YES");
continue;
}
bool flag = false;
for (int i = 1; i <= n; i++) {
if (g[i + 1] + f[i - 1] == n - 1 && a[i + 1] >= a[i - 1]) {
flag = true;
break;
}
}
if (flag) {
puts("YES");
continue;
}
a[0] = INF, a[n + 1] = 0;
for (int i = 1; i <= n; i++) {
if (a[i] <= a[i - 1]) f[i] = f[i - 1] + 1;
else f[i] = 1;
}
for (int i = n; i >= 1; i--) {
if (a[i] >= a[i + 1]) g[i] = g[i + 1] + 1;
else g[i] = 1;
}
if (g[1] == n || f[n] == n) {
puts("YES");
continue;
}
for (int i = 1; i <= n; i++) {
if (g[i + 1] + f[i - 1] == n - 1 && a[i + 1] <= a[i - 1]) {
flag = true;
break;
}
}
if (flag) puts("YES");
else puts("NO");
}
return 0;
}