2016 Multi-University Training Contest 4 1010 The All-purpose Zero

含0的最长递增子序列
本文介绍了一种特殊场景下的最长递增子序列(LIS)问题解决方法,即序列中包含0的情况下,0可以被视为任意数值。通过示例代码展示了如何利用C++实现这一算法,包括使用lower_bound函数来寻找合适位置以及特殊的剪枝优化。

题目链接:点击打开链接

题目大意:找LIS其中有0的话,0可以代替任何数。

解题思路:找到每个0之前的LIS,0作为前一段LIS的最后一位+1,前面的序列尽可能的小,于是加上一个剪枝操作,当前面的序列出现0~n,就可以剪掉了。

代码:

#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<ctime>
#include "cstdio"
#include "string"
#include "string.h"
#include "map"
#include "bitset"
using namespace std;

const int INF = 0x3f3f3f3f;
int a[100001];

int main() 
{
    int T, cas = 0;
    scanf("%d", &T);
    while(T--)
    {
        int n, x, ans = 0, pos;
        scanf("%d", &n);
        memset(a, INF, sizeof(a));
        for (int i = 0; i < n; i++) 
        {
            scanf("%d", &x);
            if (x)
            {
                pos = lower_bound(a, a + n, x) - a;
                a[pos] = x;
            }
            else 
            {
                pos = lower_bound(a, a + n, INF) - a;
                for (int j = pos - 1; j >= 0; j--) 
                {
                    a[j + 1] = a[j] + 1;
                    if (a[j] == j) 
                        break;
                }
                a[0] = 0;
            }
            ans = max(ans, pos+1);
        }
        printf("Case #%d: %d\n", ++cas, ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值