• HDU 5773 The All-purpose Zero 求LIS


    求最长上升子序列长度:

    单纯的dp时间复杂度是O(n*n)的

    dp[i] = max(dp[j]+1); (0=<j<=i-1 && a[i]>a[j]) 

    用二分可以减少查找的时间:时间复杂度:O(n*log(n))

    模板:

    #define maxn 100010
    int a[maxn], b[maxn];
    
    // 二分在b[] 数组里找第一个比num 大的数的位置。
    int search_(int num, int low, int high) {
        int mid;
        while(low <= high) {
            mid = (low+high)/2;
            if (num >= b[mid]) low = mid + 1;
            else high = mid - 1;
        }
        return low;
    }
    
    int LIS(int n) {
        int i, len, pos;
        b[1] = a[1];
        len = 1;
        for (i=2; i<=n; ++i) {
            if (a[i] > b[len]) {// 如果a[i]比b[]中最大的数还大直接插入到最后。   //如果是非递减序列,改为 >= 即可。
                len = len + 1;
                b[len] = a[i];
            }
            else {
                pos = search_(a[i], 1, len);
                b[pos] = a[i];
            }
        }
        return len;
    }

    Eg:题目链接:The All-purpose Zero

    题意:给一个序列,序列里的0可以代替任何数,问这个序列里最长递增子序列的长度。0也可以代替负数。(如果不可以的话...)

    思路:因为0可以代替任何数,所以ans一定是优先选择0的,然后把每个数减掉它前面的0的个数。为什么减0呢... 比如:1 2 0 3 优先选0,3-1=2,... ,这样就变成了1 2 2 ...求最长上升子序列的长度+0的个数。

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    using namespace std;
    
    #define maxn 100010
    int a[maxn], b[maxn];
    
    // 二分在b[] 数组里找第一个比num 大的数的位置。
    int search_(int num, int low, int high) {
        int mid;
        while(low <= high) {
            mid = (low+high)/2;
            if (num >= b[mid]) low = mid + 1;
            else high = mid - 1;
        }
        return low;
    }
    
    int LIS(int n) {
        int i, len, pos;
        b[1] = a[1];
        len = 1;
        for (i=2; i<=n; ++i) {
            if (a[i] > b[len]) {// 如果a[i]比b[]中最大的数还大直接插入到最后。   //如果是非递减序列,改为 >= 即可。
                len = len + 1;
                b[len] = a[i];
            }
            else {
                pos = search_(a[i], 1, len);
                b[pos] = a[i];
            }
        }
        return len;
    }
    
    int main() {
        //freopen("in.cpp", "r", stdin);
        int t;
        scanf("%d", &t);
        int cas = 0;
        while(t--) {
            int n;
            scanf("%d", &n);
            int zeroNum = 0, cnt = 0;
            for (int i=0; i<n; ++i) {
                int temp;
                scanf("%d", &temp);
                if (temp == 0) zeroNum++;
                else {
                    temp -= zeroNum;
                    a[++cnt] = temp;
                }
            }
            int ans = LIS(cnt) + zeroNum;
            if (cnt == 0) ans -= 1;
            printf("Case #%d: %d
    ", ++cas, ans);
        }
        return 0;
    }
  • 相关阅读:
    PHP 使用 Redis
    Redis /etc/redis.conf 常用配置
    Redis 常用操作
    Redis 操作哈希数据
    Redis 操作有序集合数据
    Redis 操作集合数据
    Redis 操作列表数据
    Redis 操作字符串数据
    Redis 安装
    Redis 简介
  • 原文地址:https://www.cnblogs.com/icode-girl/p/5721023.html
Copyright © 2020-2023  润新知