BZOJ4300 绝世好题 【dp】
题目
给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len)。
输入格式
输入文件共2行。
第一行包括一个整数n。
第二行包括n个整数,第i个整数表示ai。
输出格式
输出文件共一行。
包括一个整数,表示子序列bi的最长长度。
输入样例
3
1 2 3
输出样例
2
提示
n<=100000,ai<=2*10^9
题解
按位dp
f[i] = max{f[j] + 1} (存在A[i]二进制某位和A[j]同时为1)
这样做是
我们可以将二进制每一位为1时的最优答案储存下来,就可以做到
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int n,A[maxn][40],f[maxn],mx[40];
int main(){
n = RD(); int x;
REP(i,n){
x = RD(); f[i] = 1;
for (int j = 1; x; j++,x >>= 1){
if (A[i][j] = (x & 1)){
f[i] = max(f[i],mx[j] + 1);
}
}
for (int j = 1; j <= 32; j++)
if (A[i][j])
mx[j] = max(mx[j],f[i]);
}
int Ans = 0;
REP(i,32) Ans = max(Ans,mx[i]);
printf("%d\n",Ans);
return 0;
}