题目描述
给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len)。
输入输出格式
输入格式:输入文件共2行。 第一行包括一个整数n。 第二行包括n个整数,第i个整数表示ai。
输出文件共一行。 包括一个整数,表示子序列bi的最长长度。
输入输出样例
输入样例#1:
3
1 2 3
输出样例#1:
2
说明
对于100%的数据,1<=n<=100000,ai<=10^9。
Solution:
本题只能说数据很水。
首先很容易套上最长上升子序列的板子,我们设$f[i]$表示以第$i$个数结尾的最长序列长度,则$n^2$枚举转移。
很显然会超时,记得以前做$HNOI$的某道打鼹鼠题目时,介绍过一个玄学优化可行性剪枝(学自巨佬——hzwer),定义个$mx[i]$表示前$i$个数中的最长序列长度,若当前的$f[i]>mx[i-1]$,则直接跳出循环,因为显然最多也只能从前$i-1$个数中的最大长度$mx[i-1]+1$转移过来,而现在$f[i]$至少不比这个值小,所以也就没必要转移了,那么每次求出$f[i]$后,记住要更新$mx[i]=max(mx[i-1],f[i])$(被这卡了好一会儿!`~`),最后答案就是$mx[n]$啦。
代码:
1 #include<bits/stdc++.h> 2 #define il inline 3 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 4 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) 5 #define Max(a,b) ((a)>(b)?(a):(b)) 6 using namespace std; 7 const int N=200005; 8 int n,a[N],f[N],mx[N]; 9 10 il int gi(){ 11 int a=0;char x=getchar();bool f=0; 12 while((x<'0'||x>'9')&&x!='-')x=getchar(); 13 if(x=='-')x=getchar(),f=1; 14 while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar(); 15 return f?-a:a; 16 } 17 18 int main(){ 19 n=gi(); 20 For(i,1,n) a[i]=gi(),f[i]=1; 21 mx[1]=1; 22 For(i,2,n){ 23 Bor(j,1,i-1) 24 if(mx[i-1]<f[i])break; 25 else if((a[i]&a[j])!=0)f[i]=Max(f[i],f[j]+1); 26 mx[i]=Max(mx[i-1],f[i]); 27 } 28 cout<<mx[n]; 29 return 0; 30 }