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

  

原文地址:https://www.cnblogs.com/pkgunboat/p/11417443.html

时间: 2024-10-14 02:13:36

Codeforces 1208F Bits And Pieces 位运算 + 贪心 + dp的相关文章

codeforces 165E - Compatible Numbers 【位运算】

题目:codeforces 165E - Compatible Numbers 题意:给出n个数,然后每个数对应输出一个当前数组中与 Ai 与运算为 0 的数,没有的话输出-1 分析:简单的位运算题目,技巧性题目 首先,我们知道与运算的性质,就是只有同时为 1的时候才是1,那么假如 x&y=0 ,就是至少 x 的为1的为 y 全为0,其他为自由,假设为 1 ,那么 y = x^((1<<22)-1).但是这样并不是全部的,这些位还可能是0,所以我们可以枚举这些位,然后处理. 具体看代码

【Luogu】2114起床困难综合征(位运算贪心)

题目链接 这题真是恶心死我了. 由于位运算每一位互不干涉,所以贪心由大到小选择每一位最优的解,但是要判断一下边界,如果选择该解使得原数>m则不能选择. 代码如下 #include<cstdio> #include<cstring> #include<cctype> inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-

状态压缩中常用的位运算(DP)

面对位运算,一直很无感...可能数学太差,脑洞太小. 1.首先是最基本的: 与&,或|,非~,异或^. 2.获取一个或者多个固定位的值: 假设 x = 1010(二进制),我们要取左数第二位的值,可以用(x &(1<<1)); 还可用(x&(3<<2))来取得第三位和第四位. 3.把一个或者多个固定的位上的值清零: 同样 x = 1010(二进制),我们要使左数第二位的值清零,可以用(x^(1<<1)). 待续..

【NOI2014】起床困难综合症 位运算+贪心

这道题先求出0和-1经过处理后的答案 具体看代码吧 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int v0=0,v1=-1,ans,av,n,m,x; int main() { char ch[15]; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ scanf("%s

HDU 4317 位运算

[题意]: 在一个常规的NIM游戏里,你可以在每堆石子拿走任意数量的石子,问求使先手必败的情况下拿走石子数量的最小值. [知识点]: 位运算,DP [题解]: 一道精致的位运算的好题目,细节有不少. 具体解释在代码内. [代码]: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 #include <cstdlib> 6 #inc

位运算/CodeForces 485c Bits

1 /* 2 PROBLEM:CF 485C 3 AUTHER:Nicole 4 MEMO:位运算 二进制 5 */ 6 #include<cstdio> 7 int main() 8 { 9 int n; 10 scanf("%d",&n); 11 for (int i=1;i<=n;i++) 12 { 13 long long l,r; 14 scanf("%lld%lld",&l,&r); 15 long long x

图论/位运算 Codeforces Round #285 (Div. 2) C. Misha and Forest

题目传送门 1 /* 2 题意:给出无向无环图,每一个点的度数和相邻点的异或和(a^b^c^....) 3 图论/位运算:其实这题很简单.类似拓扑排序,先把度数为1的先入对,每一次少一个度数 4 关键在于更新异或和,精髓:a ^ b = c -> a ^ c = b, b ^ c = a; 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <cmath> 9 #include <algorith

BZOJ 3668 [Noi2014]起床困难综合症 贪心+位运算

前言:he- - 听说这是到水题,然而我考试的时候并没有做出来(自己太弱说个毛),总而言之吧,这道题告诉我: "位运算每一位互相不会干扰!!你丫这都想不到!太弱!!" 题意:链接 方法:贪心?+位运算 解析:考试的时候不知道位运算每一位不互相干扰(我真是"bi",这都想不到). 好吧然后这题就很好搞了,int找到31位,然后从后往前枚举,算每一位答案中取1或0的值,然后这个值对应这一位是1的话,只要检验答案加上这个值是不是超过m就可以了,就是这么个非常简单的贪心思路

【LeetCode从零单排】No 191.Number of 1 Bits(考察位运算)

题目 Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight). For example, the 32-bit integer '11' has binary representation 00000000000000000000000000001011, so the function should r