Codeforces 1208F Bits And Pieces 位运算 + 贪心 + dp

Posted pkgunboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1208F Bits And Pieces 位运算 + 贪心 + dp相关的知识,希望对你有一定的参考价值。

题意:给你一个序列a, 问a[i] ^ (a[j] & a[k])的最大值,其中i < j < k。

思路:我们考虑对于每个a[i]求出它的最优解。因为是异或运算,所以我们从高位向低位枚举,如果这一位a[i]是0,我们就在a[i]的右边找两个位置让它们按位与起来这位是1。那么,我们贪心的保留可以通过按位与凑出某个二进制数的最靠右的两个位置。这个可以通过dp的方式预处理出来。之后,我们枚举每一个数a[i],先找出它的哪些位是0,之后从高位到低位枚举,判断这一位是否可以变成1。如果之前已经加上的位再加上这一位可以被凑出来,那么我们就加上这一位。在所有的a[i]得出的答案中去最大值即可。

代码:

#include <bits/stdc++.h>
#define pii pair<int, int>
#define INF 0x3f3f3f3f
#define db double 
using namespace std;
const int maxn = 2000010;
pii dp[1 << 21];
int a[maxn];
void update(int mask, int val) 
	if(dp[mask].second == 0) 
		dp[mask].second = val;
		return;
	
	if(dp[mask].first == val || dp[mask].second == val) return;
	if(val > dp[mask].second) 
		dp[mask].first = dp[mask].second;
		dp[mask].second = val;
	 else if(val > dp[mask].first) 
		dp[mask].first = val;
	

void merge(int mask1, int mask2) 
	if(dp[mask2].first != 0) update(mask1, dp[mask2].first);
	if(dp[mask2].second != 0) update(mask1, dp[mask2].second);

int main() 
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) 
		scanf("%d", &a[i]);
		update(a[i], i);
	
	for (int i = 0; i < 21; i++) 
		for (int j = 0; j < (1 << 21); j++) 
			if((j >> i) & 1) 
				merge(j ^ (1 << i), j);
			
		
	
	int ans = 0;
	for (int i = 1; i <= n; i++) 
		int mask = 0, tmp = (1 << 21) - 1 - a[i];
		for (int j = 20; j >= 0; j--) 
			if((tmp >> j) & 1) 
				if(dp[mask ^ (1 << j)].first > i && dp[mask ^ (1 << j)].second != 0) 
					mask  ^= (1 << j);
				
			
		
		if(dp[mask].first > i && dp[mask].second != 0) ans = max(ans, a[i] ^ mask);
	
	printf("%d\n", ans);

  

以上是关于Codeforces 1208F Bits And Pieces 位运算 + 贪心 + dp的主要内容,如果未能解决你的问题,请参考以下文章

CF1208F Bits And Pieces

CF1208F Bits And Pieces(未解决)

[CodeForces-259C] Little Elephant and Bits

Codeforces 258E Devu and Flowers

Codeforces B - Tavas and SaDDas

Codeforces 321E Ciel and Gondolas