BZOJ4300 绝世好题 【dp】

BZOJ4300  绝世好题

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

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

题解:

一看就 dp,只不过普通 dp 是 n^2,这里不行,要按位 dp。

f[i] 是一个滚动数组,用来记录推到当前第 i 个数时,第 i 位为 1,的最长子序列长度。这样我们对于每个数,都要扫一遍每一位,在是 1 的位上取个 f[i] 的最大值 now(因为不同的一组相邻两个数不一定定要在同一位都为 1,可以不同位,所以要在这些当中取最大值),然后用 ++now 更新以当前这个数为结尾的最长子序列长度,然后再继续递推下去。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,a[1000055],ans,f[31];
 4 int main()
 5 {
 6     scanf("%d",&n);
 7     for (int i=1; i<=n; i++)
 8       scanf("%d",&a[i]);
 9     int now;
10     for (int i=1; i<=n; i++)
11     {
12         now=0;
13         for (int j=0; j<=30; j++)
14           if ((a[i] & (1<<j))!=0) now=max(f[j],now);
15         now++;
16         for (int j=0; j<=30; j++)
17           if ((a[i] & (1<<j))!=0) f[j]=max(f[j],now);
18     }
19     for (int i=0; i<=30; i++)
20       ans=max(ans,f[i]);
21     cout<<ans<<endl;
22     return 0;
23 }
View Code

加油加油加油!!! fighting fighting fighting !!!

猜你喜欢

转载自www.cnblogs.com/Frank-King/p/9227274.html