[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;
}

posted @ 2021-04-21 13:32  lahlah  阅读(30)  评论(0编辑  收藏  举报