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
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 }
加油加油加油!!! fighting fighting fighting !!!