• ZZULIOJ 1921: B 【dp + 位运算】


    1921: B

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 270  Solved: 31

    Description

    给定一个长度为n的数字序列a,从中选取一个长为m的子序列b满足 b[i]&b[i-1]!=0 (2<=i<=m)
    求最大的m。

    Input

    第一行输入一个整数t,代表有t组测试数据。
    每组数据第一行输入一个整数n代表a序列的长度,接下来一行输入n个正整数表示ai(0<i<=n)。
    1<=t<=20,0<=n<=100000,0<=ai<=1e9。

    Output

    一个整数表示最大的m。

    Sample Input

    1
    3
    1 1 1

    Sample Output

    3

    HINT

     

    Source

    这道题让我一脸懵逼状(⊙﹏⊙)b。又读错题了。。。。我以为是所有子列按位与运算。。。。我说怎么各种WA。。我说为嘛还要dp。。。。。

    思路:

    用dp记录当前状态下的每一位的最大值,对于序列中的元素, 如果这个数的第j为1, 他肯定要和前面的接上,这样就保证了他和相邻的按位与不为零,然后dp的值等于他后面的加上一。每次检查他的每一位的二进制状态,更新最值。

    对于一维的转移方程为 for  dp【i】 = max(dp【last】 + 1, dp【i】); 

    #include <bits/stdc++.h>
    using namespace std;
    const int BIT = 32;
    const int maxm = 100000 + 10;
    int a, dp[maxm], last[40];
    void init() {
        memset(dp, 0, sizeof(dp));
        memset(last, 0, sizeof(last));
    }
    bool judge_bit(int x, int y) {
        if (x & (1<<y)) return true;
        return false;
    }
    int main() {
        int n, t;
        scanf("%d", &t);
        while(t--) {
            int ans = 0; scanf("%d", &n); init();
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a);
                for(int j = 0; j <= BIT; j++) {
                    if(judge_bit(a, j)) {
                        dp[i] = max(dp[last[j]] + 1, dp[i]);
                        //last记录的是上一次 j 位为 1的位置
                        last[j] = i;
                    }
                }
                ans = max(ans, dp[i]);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }


  • 相关阅读:
    js页面跳转(转载)
    insert into select union 插入数据到sqlserver中会自动排列
    一段没用的代码
    gridview中自动生成的列不可以设置只读
    Treeview 简单遍历,赋值,检查 checkbox
    线程操作一个无限循环,cpu 占用 25% 左右
    相对路径,绝对路径互转
    遍历虚拟网站下所有目录
    一个级联关系的表,向上获取各个字段名的函数
    大家用.net 大部分的工作是在干什么
  • 原文地址:https://www.cnblogs.com/cniwoq/p/6770811.html
Copyright © 2020-2023  润新知