zoukankan      html  css  js  c++  java
  • 【洛谷】4310 绝世好题

    题目描述

    给定一个长度为 (n) 的数列 (a_i),求 (a_i) 的子序列 (b_i) 的最长长度 (k),满足 (b_i & b_{i-1} e 0),其中 (2leq ileq k), $ &$ 表示位运算取与。

    输入格式

    输入文件共 (2) 行。 第一行包括一个整数 (n)。 第二行包括 (n) 个整数,第 (i) 个整数表示 (a_i)

    输出格式

    输出文件共一行。 包括一个整数,表示子序列 (b_i) 的最长长度。

    输入输出样例

    输入 #1

    3
    1 2 3
    

    输出 #1

    2
    

    题解

    对于任意一个数 (b_i) 要满足条件 (b_i&b_{i-1} e 0)(namo) (b_i) 中存在二进制为 (1) 的位置与 (b_{i-1}) 中二进制为 (1) 的位置存在交集

    目前而言只知道 (b_i) 需要寻找交集,则就是去进行枚举每一个位置,当 (b_i) 的这个位置二进制为 (1) ,进行寻找最大值

    (b[i] = max(b[j]+1))(b_i&b_j e 0)

    算到这里时间复杂度是 (O(n^2)) ,需要进行优化,

    (namo) 就是保存一下记录 (i) 最近的,当前位置的二进制为 (1) 的位置。

    也就是说使用一个数组 (cnt)(cnt_j) 表示距离当前位置最近并且 (b_k) 的第 (j) 的二进制为 (1) 的位置

    代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5+55;
    int cnt[80];
    ll a[maxn];
    int b[maxn];
    int main(){
    	memset(cnt,0,sizeof(cnt));
    	int n,maxx=0;
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%lld",&a[i]);
    		for(int j=0;j<40;++j){
    			if((a[i]>>j)&1){
    				b[i]=max(b[cnt[j]]+1,b[i]);
    				cnt[j]=i;
    			}
    		}
    		maxx=max(maxx,b[i]);
    	}
    	printf("%d
    ",maxx);
    	return 0;
    }
    
    新赛季的开始
  • 相关阅读:
    大话设计模式——UML图
    IdentityServer3零星笔记
    Angular路由
    基于jquery的静态页面翻页
    00_python安装与配置(mac)
    OracleParameter.UdtTypeName的值必须是全大写!
    VS2012调用64位IIS Express
    MVC中使用Ueditor
    优秀博客站点
    jqGrid中的formatter
  • 原文地址:https://www.cnblogs.com/VagrantAC/p/13266251.html
Copyright © 2011-2022 走看看