• 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;
    }
  • 相关阅读:
    Matlab随笔之三维图形绘制
    Matlab随笔之模拟退火算法
    Matlab随笔之矩阵入门知识
    Matlab随笔之求解线性方程
    Matlab随笔之分段线性函数化为线性规划
    Matlab随笔之指派问题的整数规划
    Matlab随笔之线性规划
    Android单位转换 (px、dp、sp之间的转换工具类)
    Android禁止输入表情符号
    设计模式之策略模式
  • 原文地址:https://www.cnblogs.com/five20/p/9108230.html
Copyright © 2020-2023  润新知