Evanyou Blog 彩带

P4310 绝世好题

题目描述

给定一个长度为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]$啦。

代码:

 

#include<bits/stdc++.h>
#define il inline
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=200005;
int n,a[N],f[N],mx[N];

il int gi(){
    int a=0;char x=getchar();bool f=0;
    while((x<'0'||x>'9')&&x!='-')x=getchar();
    if(x=='-')x=getchar(),f=1;
    while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
    return f?-a:a;
}

int main(){
    n=gi();
    For(i,1,n) a[i]=gi(),f[i]=1;
    mx[1]=1;
    For(i,2,n){
        Bor(j,1,i-1)
        if(mx[i-1]<f[i])break;
        else if((a[i]&a[j])!=0)f[i]=Max(f[i],f[j]+1);
        mx[i]=Max(mx[i-1],f[i]);
    }
    cout<<mx[n];
    return 0;
}

 

 

 

 

posted @ 2018-05-29 22:12  five20  阅读(184)  评论(0编辑  收藏  举报
Live2D