• BZOJ4300 绝世好题 【dp】


    题目

    给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len)。

    输入格式

    输入文件共2行。
    第一行包括一个整数n。
    第二行包括n个整数,第i个整数表示ai。

    输出格式

    输出文件共一行。
    包括一个整数,表示子序列bi的最长长度。

    输入样例

    3

    1 2 3

    输出样例

    2

    提示

    n<=100000,ai<=2*10^9

    题解

    按位dp
    f[i] = max{f[j] + 1} (存在A[i]二进制某位和A[j]同时为1)
    这样做是O(n2)
    我们可以将二进制每一位为1时的最优答案储存下来,就可以做到O(32n)的复杂度

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    using namespace std;
    const int maxn = 100005,maxm = 100005,INF = 1000000000;
    inline int RD(){
        int out = 0,flag = 1; char c = getchar();
        while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
        while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
        return out * flag;
    }
    int n,A[maxn][40],f[maxn],mx[40];
    int main(){
        n = RD(); int x;
        REP(i,n){
            x = RD(); f[i] = 1;
            for (int j = 1; x; j++,x >>= 1){
                if (A[i][j] = (x & 1)){
                    f[i] = max(f[i],mx[j] + 1);
                }
            }
            for (int j = 1; j <= 32; j++)
                if (A[i][j])
                    mx[j] = max(mx[j],f[i]);
        }
        int Ans = 0;
        REP(i,32) Ans = max(Ans,mx[i]);
        printf("%d
    ",Ans);
        return 0;
    }
    
  • 相关阅读:
    https://blog.csdn.net/nameofcsdn/article/details/53164652
    洛谷
    模板
    模板
    Gym 101911E "Painting the Fence"(线段树区间更新+双端队列)
    Gym 101911F “Tickets”
    图论:最小瓶颈生成树
    图论:次小生成树
    图论:费用流-SPFA+EK
    图论:Dinic算法
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282710.html
Copyright © 2020-2023  润新知