博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj4300】绝世好题 dp
阅读量:5219 次
发布时间:2019-06-14

本文共 999 字,大约阅读时间需要 3 分钟。

题目描述

给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len)。

输入

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

输出

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

样例输入

3

1 2 3

样例输出

2


题解

dp

设f[i]为选i时前i个元素的最多个数。

那么就有f[i]=max{f[j]}+1 (a[j]&a[i]!=0)

这样会TLE,于是想优化。

如果a&b!=0,根据定义,a、b的二进制数中至少有一位都为1。

那么我们可以开一个辅助数组maxn[k],记录一下所有a[i]中二进制第k位为1的f[i]的最大值。

然后扫一遍每个a[i]的数位,取最大值加到f[i]里并更新即可。

#include 
#include
using namespace std;int a[100010] , f[100010] , maxn[32];int getnum(int n){ int i; for(i = 0 ; i < 31 ; i ++ ) if((1 << i) == n) return i; return 0;}int main(){ int n , i , j , t , ans = 0; scanf("%d" , &n); for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]); for(i = 1 ; i <= n ; i ++ ) { f[i] = 1; for(j = a[i] ; j ; j -= j & (-j)) f[i] = max(f[i] , maxn[getnum(j & (-j))] + 1); for(j = a[i] ; j ; j -= j & (-j)) { t = getnum(j & (-j)); maxn[t] = max(maxn[t] , f[i]); } ans = max(ans , f[i]); } printf("%d\n" , ans); return 0;}

 

转载于:https://www.cnblogs.com/GXZlegend/p/6498432.html

你可能感兴趣的文章
Javascript 学习杂记
查看>>
HDU 1244 Max Sum Plus Plus Plus
查看>>
UVa 10817 (状压DP + 记忆化搜索) Headmaster's Headache
查看>>
UVa 11107 (后缀数组 二分) Life Forms
查看>>
HDU 4738 双连通分量 Caocao's Bridges
查看>>
UVa 1455 Kingdom 线段树 并查集
查看>>
Expression拼接
查看>>
有关js弹出提示框几种方法
查看>>
.NET简谈事务本质论
查看>>
php 正则中文匹配
查看>>
java 如何在pdf中生成表格
查看>>
优化学习笔记5
查看>>
Speeding up image loading in WPF using thumbnails
查看>>
信1405-1班20142886杜若憧
查看>>
洋灰三角(矩阵快速幂的两种解法)
查看>>
九九乘法表
查看>>
[转]阅读tesseract-OCR(3.01)程序源码的一点心得体会
查看>>
springSide部署出现AnnotationConfigUtils.processCommonDefinitionAnnotations(…) is not public!
查看>>
ThinkPHP隐藏入口文件的配置方法
查看>>
20180708-Java变量类型
查看>>