zoukankan      html  css  js  c++  java
  • P4310 绝世好题 [位运算优化dp]

    题目描述

    给定一个长度为 (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

    说明/提示

    对于(100\%)的数据,(1leq nleq 100000)(a_ileq 10^9)

    分析

    看到题的第一反应就被标签里的枚举给迷惑到了,然后快速打了一个暴力枚举,显然直接(90)(TLE)了,然后开始想正解。

    首先题目中的条件是含有位运算的,我们就可以从这里开始入手优化。

    因为题目中给的条件是(a_i&a_{i-1} eq 0),所以这就证明了只要两个数之间有一个二进制位上相同的(1)就可以让长度加一,那么我们就可以枚举每一个二进制位,找出他们与运算后是否为(0),如果不是(0)就让长度加一,我们的一个状态转移方程就出来了:

    [Max = max(dp[c]+1,Max) ]

    其中(dp[c])是二进制第(c)位时最大的长度,当前状态下满足条件就加一,然后与最大长度(Max)取最大值。

    需要注意的一个地方就是我们在状态转移后需要每次更新一下(dp[c]),因为当前满足条件的最长长度已经找出来是(Max)了,所以所有当前满足条件的二进制位的最大长度都变为(1),那么就又有一个转移:

    [dp[c]=Max ]

    最后再统计一下所有更新后(Max)的最大值就好了。

    代码

    首先先放一下我的暴力(90points)代码

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

    然后是正解:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 32;
    int dp[maxn];
    int Max,ans;
    int main(){
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		int b;
    		scanf("%d",&b);
    		for(int c=0;c<=31;++c){//枚举每一个二进制位
    			if((1<<c)&b)Max=max(Max,dp[c]+1);
    		}
    		for(int c=0;c<=31;++c){//更新满足条件的二进制位的最大值
    			if((1<<c)&b)dp[c]=max(Max,dp[c]);
    		}
    		ans=max(ans,Max);//统计最大值答案
    	}
    	cout<<ans<<"
    ";
    	return 0;
    }
    
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    chrome标签记录——关于各类性能优化
    JavaScript(二)——在 V8 引擎中书写最优代码
    JavaScript学习(一)——引擎,运行时,调用堆栈
    MySQL数据库操作生成UUID
    使用Spring MVC实现文件上传与下载
    敏捷过程(小规模团队敏捷开发)
    后台获取日期值,前台Js对日期进行操作
    搭建Spring相关框架后,配置信息文件头部出现红色小×错误。
  • 原文地址:https://www.cnblogs.com/Vocanda/p/13268588.html
Copyright © 2011-2022 走看看