【BZOJ 4300】绝世好题

4300: 绝世好题

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 540  Solved: 278
[Submit][Status][Discuss]

Description

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

 

Input

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

 

Output

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

 

Sample Input

3
1 2 3

Sample Output

2

HINT

 

对于100%的数据,1<=n<=100000,ai<=10^9。


 

 

Source

 
题目如此之霸气,然而内在却水得一败涂地。
然而不难想到O(N2)的算法,就是一个简单LIS,条件不同罢了。
加一点优化,我们不难知道我们只要从前面选一个最大加1就行了(LIS就是这么做的哦),所以我们需要一个快速查找的东西。
我们把数都看成二进制(最长也只有31位),那么我们只需要知道当前这个数的某一二进制位和前面的都是1,那么&运算后的结果肯定不为0了。
很简单吧。就这样就变成O(Nlog2ai)的算法。虽然表达有点诡异,但是大家懂了就行。
#include <cstdio>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
int maxbit[35], a, n;
 
void update(int x, int delx)
{
    for (int i = 0; x != 0; (x >>= 1), ++i)
        if (x & 1) maxbit[i] = max(maxbit[i], delx);
}
 
int query(int x)
{
    int maxt = 0;
    for (int i = 0; x != 0; (x >>= 1), ++i)
        if (x & 1) maxt = max(maxt, maxbit[i]);
    return maxt;
}
 
int main()
{
    scanf("%d", &n);
    scanf("%d", &a);
    int ans = 1;
    memset(maxbit, 0, sizeof(maxbit));
    update(a, 1);
    for (int i = 1; i < n; ++i)
    {
        scanf("%d", &a);
        int maxnow = query(a) + 1;
        update(a, maxnow);
        ans = max(ans, maxnow);
    }
    printf("%d\n", ans);
    return 0;
}

 

posted @ 2015-11-13 22:21  albertxwz  阅读(655)  评论(0编辑  收藏  举报