码迷,mamicode.com
首页 > 其他好文 > 详细

P4310 绝世好题 题解

时间:2020-07-08 19:29:07      阅读:37      评论:0      收藏:0      [点我收藏+]

标签:lan   bit   二进制   复杂   code   print   com   题解   分析   

题目描述

技术图片

分析

第一次看这道题首先想到的就是时间复杂度为\(\ n^{2}\)的求最长上升子序列

    for(int i=1;i<=n;i++){
        f[i]=1;
        for(int j=1;j<i;j++){
            if((a[i]&a[j])!=0) f[i]=max(f[i],f[j]+1);
        }
        ans=max(ans,f[i]);
    }

判断时把条件改一下就好了

但是这一道题的数据范围达到了\(10^{5}\),这样写会超时

所以我们考虑更优秀的算法,突破口就是位运算

题目中的操作是按位与,所以我们可以把一个数的每一个二进制位分别拆分进行计算

我们设\(f[i]\)为当前二进制位为\(i\)时满足要求的最长长度

我们用一个变量\(k\)记录当前位置的最大状态

要注意的是,最大状态要在所有为\(1\)的位中转移

比如下面这组数据

011

110

100

在转移到第二位的时候要取一个最大值

最后不要忘了用这个值去更新\(f\)

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,a[maxn],ans;
int f[300];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;++i){
	    int now=1;
		for(int j=0;j<=30;j++){
		    if(a[i]&(1<<j)){
		        now=max(now,f[j]+1);
		    } 
		}
		for(int j=0;j<=30;j++){
		    if(a[i]&(1<<j)){
		        f[j]=max(f[j],now);
		    }
		}
       ans=max(ans,now);
	}
	printf("%d\n",ans);
	return 0;
}

P4310 绝世好题 题解

标签:lan   bit   二进制   复杂   code   print   com   题解   分析   

原文地址:https://www.cnblogs.com/liuchanglc/p/13268579.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!