您的位置:首页 > 其它

【BZOJ 4300】绝世好题

2015-11-13 22:21 441 查看

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

By Oxer

题目如此之霸气,然而内在却水得一败涂地。
然而不难想到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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: