这道题的链接:https://pintia.cn/problem-sets/994805148990160896/problems/994805150479138816
这道题很明显是考最长递增序列,用LIS O(NlgN)算法,从网上看了别人写的大多用dp但耗时太长,有用LIS的但却用的不够准确。在LIS时加一个数组nu 记录:到该下标的数时的最长递增序列为多少。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 10005
int n;
int Bisearch(int len, int w,int *List) {
int l = 1, r = len;
int mid;
while (l <= r) {
mid = (l + r) / 2;
if (List[mid] > w)
r = mid - 1;
else if (List[mid] < w)
l = mid + 1;
else
return mid;
}
return l;
}
int LIS(int *a,int *List, int *nu ) {
int len = 1;
int pos;
List[1] = a[1];
nu[1] = 1;
for (int i = 2; i <= n; i++) {
if (a[i] > List[len]) {
List[++len] = a[i];
nu[i] = len;
}
else {
pos = Bisearch(len, a[i], List);
List[pos] = a[i];
//cout <<i<<" "<< pos << endl;
nu[i] = pos;
}
}
return len;
}
int main() {
int nu[N], nu1[N], nu2[N];
int a[N], b[N], List[N], List1[N];
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for (int i = n, j = 1; j <= n; j++, i--) {
b[i] = a[j];
}
int lena = LIS(a, List, nu);
if (lena == 1 || lena == n) {
cout << "No peak shape" << endl;
return 0;
}
int lenb = LIS(b, List1, nu1);
for (int i = 1, j = n; i <= n; j--, i++)
{
nu2[i] = nu1[j];
}
int mx = -1;
int cha = 10 * N;
int t;
for (int i = 1; i <= n; i++) {
//cout << nu[i] << " " << nu2[i] << endl;
if (nu[i] > 1 && nu2[i] > 1)
{
if (nu[i] + nu2[i] >= mx) {
if (nu[i] + nu2[i] == mx) {
if (abs(nu[i] - nu2[i]) <= cha) {
t = i;
cha = abs(nu[i] - nu2[i]);
}
}
else {
mx = nu[i] + nu2[i];
t = i;
cha = abs(nu[i] - nu2[i]);
}
}
}
}
if (mx == -1) {
cout << "No peak shape" << endl;
return 0;
}
cout << mx - 1 << " " << t << " " << a[t] << endl;
return 0;
}