zoukankan      html  css  js  c++  java
  • Luogu 4310 绝世好题

    BZOJ 4300

    先把这堆东西丢到博客里,以后再复习。

    首先考虑暴力的$dp$,设$f_i$表示以$i$结尾的满足条件的序列的最长长度,有:

        $f_i = max(f_j) + 1$    $j < i $ $,$  $ a_j & a_i eq 0$

        $ans = max(f_i)$    $1 leq i leq n$

    这样是$n^2$的。

    考虑二进制意义下的按位与,如果要使这个运算的结果不为$0$的话,必须要有一位两个数都是$1$,那么我们可以考虑拆位进行$dp$,设$g_j$表示第$j$位是$1$结尾的最长的满足条件的序列的长度。对于每一个$i$,有:

        $f_i = max(g_j) + 1$   $0 leq j leq 32$  并且$a_i$的第$j$位为$1$。

        $g_j = max(f_i, g_j)$   $a_i$的第$j$位为$1$。

        $ans = max(f_i)$    $1 leq i leq n$

    事实上在写的时候并没有必要把$f$开出来。

    时间复杂度$O(nlog(Maxn))$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 1e5 + 5;
    const int M = 35;
    
    int n, a[N], f[M];
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline void chkMax(int &x, int y) {
        if(y > x) x = y;
    }
    
    int main() {
        read(n);
        for(int i = 1; i <= n; i++) read(a[i]);
        
        int ans = 0;
        for(int i = 1; i <= n; i++) {
            int now = 0;
            for(int j = 0; j <= 32; j++)
                if((a[i] >> j) & 1) chkMax(now, f[j]);
            ++now;
            chkMax(ans, now);
            for(int j = 0; j <= 32; j++)
                if((a[i] >> j) & 1) chkMax(f[j], now);
        }
        
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    第二天续
    使用git提交本地仓库每次需要输入账号密码的问题解决
    第二天
    开启远程之路
    第一天
    第一步了解并且安装配置
    6
    Algorithms
    Algorithms
    Algorithms
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9738725.html
Copyright © 2011-2022 走看看