您的位置:首页 > Web前端

UVA - 1471 Defense Lines 贪心+二分

2015-04-15 09:35 369 查看
题目大意:给出长度为n的序列,要求你删除掉一段的连续子序列,使得剩下的序列的递增子序列最长

解题思路:记录以下每个位置的值所能延伸的最左端和最右端,用一个数组记录长度为i的数的最小值,然后从左往右扫描,用二分搜索在数组中找到小于当前值的数的位置,用当前数的right + len - 1就是结果了,再维护一下最大值

[code]#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
 = 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: