BZOJ4300: 絕世好題(dp)
阿新 • • 發佈:2018-06-25
col sample get color mem space for size return Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 2751 Solved: 1493
[Submit][Status][Discuss]
3
1 2 3
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
1 2 3
Sample Output
2HINT
n<=100000,ai<=2*10^9
Source
題目簡潔好評
$n^2$的dp比較無腦,但是肯定過不了
剛開始我以為這玩意兒有決策單調性,但是很顯然是錯的。。
正解充分利用了$&$的性質,我們直接用$f[i]$表示第$i$位不為$0$時的最大值
轉移的時候枚舉這一位是不是$0$就可以了
#include<cstdio> #include<algorithm> #define int long long usingnamespace 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)