题目链接
题目描述
给出 n n n对数字,每对第一个为 n u m num num,每对第二个为 v a l val val,求在若干个 n u m num num异或和不为 0 0 0的时候的 v a l val val和的最大值。
题目思路
我们对每对数据的val进行排序,然后插入每个的 n u m num num,如果能插入就加上此时的 v a l val val,这运用了贪心的思想。
为什么呢?我一开始也提问,如果有 a , b , c , d , e a,b,c,d,e a,b,c,d,e多组数据按照 v a l val val依次递减,有没有可能不选 a a a呢?(因为 a a a的 n u m num num是第一个插入的,必定选)
你认为
b
b
b和
c
c
c在一起搭配
v
a
l
val
val的和可能比a的和大,错了,那么我
a
a
a和
b
b
b肯定更大,这样可能不能理解,那么我们这样看:假如
a
,
b
,
c
a,b,c
a,b,c的
n
u
m
num
num异或和为
0
0
0,说明不能同时取,这是和最优解肯定是
a
,
b
a,b
a,b一起然后不选
c
c
c,这时候我们找下面的d,e,这样的话有两种情况:1)如果d ^ e = c
的话我们只能选其中一个,不然a ^ b ^ d ^ e = 0
,那我们肯定选d;2)如果d ^ e != c
那么我们都可以选。
能不能选a的问题还是没有解决,假如我选了 b , c b,c b,c不选 a a a,此时也是两种情况,一种只能选一个,一种多选,那么我肯定选择 a a a而不是选择 c c c,因为 a . v a l ≥ c . v a l a.val \geq c.val a.val≥c.val,所以这种贪心是正确的。
代码
ll p[N],x,ans,d[N],cnt,flag;
int n,m;
struct node
{
ll num,val;
}a[N];
inline bool insert(ll x)
{
for (int i=62;i>=0;i--)
if (x>>i)
if (p[i])
x^=p[i];
else
{
p[i]=x;
return 1;//插入成功
}
return 0; //插入失败
}
bool cmp(node x,node y)
{
return x.val>y.val;
}
inline void Case_Test()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i].num>>a[i].val;
sort(a+1,a+1+n,cmp);
for (int i=1;i<=n;i++)
if (insert(a[i].num))//插入成功
ans+=a[i].val;
cout<<ans;
}