P4570 [BJWC2011]元素 题解

\(Solution\)

我们看到这个魔法抵消,也就是不能有异或和为 \(0\) 的子集,我们想到了线性基的性质:

线性基里没有异或和为 \(0\) 的子集。

证明非常明显:\(P_i\) 的最高位都不同,异或后肯定不为 \(0\)

我们再考虑贪心,我们想让他的价值最大,我们就要尽量的把价值大的先加进去。

所以我们考虑从价值大的开始加,能加就加,如果加不上就不加。

/*
	Work by: TLE_Automation
*/
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define int long long
using namespace std;

const int N = 1e6 + 10;
const int MAXN = 2e5 + 10;

inline char readchar() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read() {
#define readchar getchar
	int res = 0, f = 0;char ch = readchar();
	for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
	return f ? -res : res;
}

inline void print(int x) {
	if (x < 0 ) putchar('-'), x = -x;
	if (x > 9 ) print(x / 10);
	putchar(x % 10 + '0');
}

int d[100];

struct _Node {
	int bh, Val;
	bool operator < (const _Node&x) const {
		return Val > x.Val;
	}
}a[N];

bool Insert(int x) {
	for(int i = 63; i >= 0; i--) {
		if(x & (1ll << i)) {
			if(d[i]) x ^= d[i];
			else {
				d[i] = x; return true;
			}
		}
	}
	return false;
}
int ans = 0;

signed main() {
	int n = read();
	for(int i = 1; i <= n; i++) a[i].bh = read(), a[i].Val = read();
	sort(a + 1, a + n + 1);
	for(int i = 1; i <= n; i++) if(Insert(a[i].bh)) ans += a[i].Val;
	print(ans);
}
posted @ 2022-05-22 14:57  TLE_Automation  阅读(23)  评论(1)    收藏  举报