题目链接:戳我
如何保证选出来一些数,他们任意一个子集的异或和不为0?
显然可以用线性基维护一下。
那么如何求选出来的数的元素值最大呢?我们排序一下子就好啦!将元素按照从大到小排序。至于原因,和上一道题一样。
不过请注意,这个题的id值在long long范围内,线性基中的左移操作记得开1ll
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define MAXN 100010
using namespace std;
int n;
int a[MAXN];
long long tot;
long long p[MAXN];
struct Node{long long id;int sum;}node[MAXN];
inline bool cmp(struct Node x,struct Node y){return x.sum>y.sum;}
inline void insert(long long x)
{
for(int i=63;i>=0;i--)
{
if(x&(1ll<<i))
{
if(!p[i]){p[i]=x;break;}
x^=p[i];
}
}
}
inline long long query(long long x)
{
for(int i=63;i>=0;i--)
{
if(x&(1ll<<i))
{
if(p[i]) x^=p[i];
}
}
return x;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld%d",&node[i].id,&node[i].sum),tot+=node[i].sum;
sort(&node[1],&node[n+1],cmp);
long long cur_ans=0;
for(int i=1;i<=n;i++)
{
if(query(node[i].id)==0) cur_ans+=node[i].sum;
else insert(node[i].id);
}
// printf("%lld\n",cur_ans);
printf("%lld\n",tot-cur_ans);
return 0;
}