BJWC2011 元素

题目链接:戳我

如何保证选出来一些数,他们任意一个子集的异或和不为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;
}
posted @ 2019-05-15 11:19  风浔凌  阅读(128)  评论(0编辑  收藏  举报