题目大意:给出长度为n的序列,要求你删除掉一段的连续子序列,使得剩下的序列的递增子序列最长
解题思路:记录以下每个位置的值所能延伸的最左端和最右端,用一个数组记录长度为i的数的最小值,然后从左往右扫描,用二分搜索在数组中找到小于当前值的数的位置,用当前数的right + len - 1就是结果了,再维护一下最大值
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 200010
int num[maxn], l[maxn], r[maxn], Min[maxn];
int main() {
int test, n;
scanf("%d", &test);
while(test--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &num[i]);
l[1] = 1;
for(int i = 2; i <= n; i++)
l[i] = num[i] > num[i - 1] ? l[i - 1] + 1: 1;
r[n] = 1;
for(int i = n - 1; i >= 1; i--)
r[i] = num[i] < num[i + 1] ? r[i + 1] + 1: 1;
int ans = 0;
memset(Min,0x3f,sizeof(Min));
for(int i = 1; i <= n; i++) {
int len = lower_bound(Min+1,Min+1+n,num[i]) - Min;
ans = max(ans,r[i] + len - 1);
Min[l[i]] = min(Min[l[i]],num[i]);
}
printf("%d\n",ans);
}
return 0;
}