【BZOJ 4300】绝世好题
4300: 绝世好题
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 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
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; }