【递推】BZOJ 4300:绝世好题

4300: 绝世好题

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 564  Solved: 289
[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

Sample Output

2

HINT

对于100%的数据,1<=n<=100000,ai<=10^9。


 

  刚考完联赛回家搞了一个星期常规=- =

  然后老师叫我们还是要保持一下手感的是吧

  然后随便找了一道水题。。

  貌似是单调DP?

  发现不行

  然后想了一下按位单调DP

  感觉好像可以但不是最优解。。

  看了一下status

  发现最短的代码400b左右

  貌似不是单调DP?

  然后查了一下。。

  f[j]代表第j位的最优值

  之后每次更新一个数每一位的最优值为所有位的f值+1即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5  
 6 #define maxn 100001
 7  
 8 using namespace std;
 9  
10 int a[maxn],f[maxn];
11  
12 inline int in()
13 {
14     int x=0;char ch=getchar();
15     while(ch<'0'||ch>'9')ch=getchar();
16     while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
17     return x;
18 }
19  
20 int main()
21 {
22     int n;
23     n=in();
24     for(int i=1;i<=n;i++)a[i]=in();
25     for(int i=1;i<=n;i++)
26     {
27         int cal=0;
28         for(int j=0;j<=30;j++)if(a[i] & (1<<j))cal=max(cal,f[j]+1);
29         for(int j=0;j<=30;j++)if(a[i] & (1<<j))f[j]=cal;
30     }
31     int ans=0;
32     for(int j=0;j<=30;j++)ans=max(ans,f[j]);
33     printf("%d",ans);
34     return 0;
35 }
View Code

 

posted @ 2015-11-18 18:50  puck_just_me  阅读(...)  评论(... 编辑 收藏