【BZOJ4300】绝世好题(动态规划)

【BZOJ4300】绝世好题(动态规划)

题面

BZOJ

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\)

题解

考虑一个\(O(n^2)\)\(dp\)
\(f[i]=max(f[j]+1),b[i]\ and\ b[j]≠0\)
仔细想想,没必要访问所有的\(j\)
只需要访问对于每一个二进制位,上一次出现过的\(j\)就可以啦
复杂度\(O(nlogn)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 111111
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int n,a[MAX],f[MAX],ans;
int lst[65];
int main()
{
	n=read();
	for(int i=1;i<=n;++i)a[i]=read();
	for(int i=1;i<=n;++i)f[i]=1;
	for(int i=1;i<=n;++i)
		for(int j=0;j<31;++j)
			if(a[i]&(1<<j))f[i]=max(f[i],f[lst[j]]+1),lst[j]=i;
	for(int i=1;i<=n;++i)ans=max(ans,f[i]);
	printf("%d\n",ans);
	return 0;
}

posted @ 2018-03-16 21:35  小蒟蒻yyb  阅读(258)  评论(0编辑  收藏  举报