【递推】BZOJ 4300:绝世好题
4300: 绝世好题
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 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
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 }