UVA 1471 - Defense Lines(扫描+二分)

来源:互联网 发布:php中连接符 编辑:程序博客网 时间:2024/05/16 09:47

UVA 1471 - Defense Lines

题目链接

题意:给定一个序列,要求删去一个连续子序列后,得到的序列有一个最长的连续递增序列,输出最长连续递增序列长度

思路:先左右扫描一遍,把每个位置往左和往右的最大长度记录下来,然后在从左往右扫描一遍,开一个数组Min用来记录长度i的序列,最后一位的最小值,这个序列是满足单调性的,因为递增序列肯定是1,2,3,4...这样不断往上加的,如果遇到一个a[i]比较小的,就维护Min相应长度下的值,这样在这个单调递增的序列中,每次就可以二分找出最后一位小于a[i],然后和当前位置往右的序列长度拼接起来,得到一个长度,记录下最大值就是答案

代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int N = 200005;int t, n, a[N], left[N], right[N], Min[N];void init() {    scanf("%d", &n);    left[0] = 1; right[n - 1] = 1;    for (int i = 0; i < n; i++) {scanf("%d", &a[i]);if (i) {    left[i] = 1;    if (a[i] > a[i - 1]) left[i] += left[i - 1];}    }    for (int i = n - 2; i >= 0; i--) {right[i] = 1;if (a[i] < a[i + 1]) right[i] += right[i + 1];    }}int solve() {    int ans = 0;    memset(Min, INF, sizeof(Min));    for (int i = 0; i < n; i++) {int len = lower_bound(Min + 1, Min + 1 + n, a[i]) - Min;ans = max(ans, right[i] + len - 1);Min[left[i]] = min(Min[left[i]], a[i]);    }    return ans;}int main() {    scanf("%d", &t);    while (t--) {init();printf("%d\n", solve());    }    return 0;}


1 0
原创粉丝点击