[CF gym 102956D] Bank Security Unification
https://codeforces.ml/gym/102956/problem/D
题目大意
给定一个序列 a 1 , … , a n a1,…,an a1,…,an,你需要从中选出一个子序列,使得相邻两项按位与的和最大。
n < = 1 e 6 n<=1e6 n<=1e6
题解
首先可以想到一个很简单的
O
(
n
2
)
O(n^2)
O(n2)的DP,然后发现转移的时候可以只用枚举两个数的与的最高位转移,然后就无了
具体看代码吧
code:
#include<bits/stdc++.h>
#define N 2000050
#define ll long long
using namespace std;
int n, pre[N];
ll a[N], f[N];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%lld", &a[i]);
ll ans = 0;
for(int i = 1; i <= n; i ++) {
for(int j = 0; j <= 45; j ++) if((a[i] >> j) & 1){
f[i] = max(f[i], f[pre[j]] + (a[pre[j]] & a[i]));
pre[j] = i;
}
ans = max(ans, f[i]);
f[i] = max(ans, f[i]);
}
printf("%lld", ans);
return 0;
}