1. 程式人生 > >BZOJ4300: 絕世好題(dp)

BZOJ4300: 絕世好題(dp)

col sample get color mem space for size return

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 2751 Solved: 1493
[Submit][Status][Discuss]

Description

給定一個長度為n的數列ai,求ai的子序列bi的最長長度,滿足bi&bi-1!=0(2<=i<=len)。

Input

輸入文件共2行。 第一行包括一個整數n。 第二行包括n個整數,第i個整數表示ai。

Output

輸出文件共一行。 包括一個整數,表示子序列bi的最長長度。

Sample Input

3
1 2 3

Sample Output

2

HINT

n<=100000,ai<=2*10^9


Source

題目簡潔好評

$n^2$的dp比較無腦,但是肯定過不了

剛開始我以為這玩意兒有決策單調性,但是很顯然是錯的。。

正解充分利用了$&$的性質,我們直接用$f[i]$表示第$i$位不為$0$時的最大值

轉移的時候枚舉這一位是不是$0$就可以了

#include<cstdio>
#include<algorithm>
#define int long long 
using
namespace std; const int MAXN = 1e5 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < 0 || c > 9) {if(c == -) f = -1; c = getchar();} while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * f; } int a[MAXN], f[33
], B = 32; main() { int N = read(), out = 0; for(int i = 1; i <= N; i++) a[i] = read(); for(int i = 1; i <= N; i++) { int ans = 0; for(int j = B; j >= 0; j--) if(a[i] & (1 << j)) ans = max(ans, f[j] + 1); for(int j = B; j >= 0; j--) if(a[i] & (1 << j)) f[j] = ans; } for(int i = 0; i <= B; i++) out = max(out, f[i]); printf("%d", out); }

BZOJ4300: 絕世好題(dp)