zoukankan      html  css  js  c++  java
  • [题解]BZOJ2460元素

    传呀传送门

    题目描述

    给出n个元素,每一个元素有一个数值(a_i)和价值(b_i)

    定义子集(S)的价值为(sum b[i]),求(a)的异或值不为0的子集中,价值的最大值

    分析

    一篇有理有据的题解

    嗯就是线性基+贪心

    2019.10.20update:果然我又回来重新学线性基了。为啥这个那么草率的呀

    把所有元素按照(b[i])排序,然后一个个插入线性基中

    • 如果可以插入:那么直接插入,并把答案加上当前的(b[i])
    • 否则:说明线性基中存在(d[x]oplus d[y]oplus...oplus d[z]=b[i]),如果要把(b[i])插进去,必然需要撤销掉之前所选择的一些元素,但由于我们已经按照(b[])排好序了,这样显然是不优的

    之前在想会不会从原先的线性基中删去一个可以插入两个新的元素。然后发现这个显然是不可能的

    代码

    #include<bits/stdc++.h>
    #define rep(X,A,B) for(int X=A;X<=B;X++)
    #define tep(X,A,B) for(int X=A;X>=B;X--)
    #define LL long long
    const int N=1000010;
    const int M=2000010;
    const int maxn=60;
    using namespace std;
    
    void read(int &x){
    	x=0;char c=getchar();
    	for(;c<'0'||c>'9';c=getchar());
    	for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^48);
    }
    
    void read(LL &x){
    	x=0;char c=getchar();
    	for(;c<'0'||c>'9';c=getchar());
    	for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^48);
    }
    
    struct nn{
    	LL num;
    	int val;
    }a[N];
    
    int cmp(nn A,nn B){
    	return A.val>B.val;
    }
    
    int n;
    LL d[N];
    
    void READ(){
    	read(n);
    	rep(i,1,n)read(a[i].num),read(a[i].val);
    	sort(a+1,a+n+1,cmp);
    }
    
    int INS(LL x){
    	tep(i,60,0){
    		if(!((x>>i)&1))continue;
    		if(!d[i]){
    			d[i]=x;
    			return 1;
    		}
    		x^=d[i];
    	}
    	return 0;
    }
    
    int SOLVE(){
    	int ans=0;
    	rep(i,1,n)if(INS(a[i].num))ans+=a[i].val;
    	return ans;
    }
    
    int main(){
    	READ();
    	printf("%d
    ",SOLVE());
    	return 0;
    }
    
  • 相关阅读:
    操作系统——生产者消费者
    flutter如何搭建android环境
    小程序uni-app图片预览uni.previewImage会触发onshow这个生命周期
    小程序 uni-app动态更改标题
    小程序uni-app处理input框将页面往上推动的解决办法
    去除小程序scroll-view产生的横向滚动条
    小程序生命周期详解
    h5移动端像素适配 postcss-pxtorem和amfe-flexible
    vue平铺日历组件
    组合数
  • 原文地址:https://www.cnblogs.com/SCL123/p/10745182.html
Copyright © 2011-2022 走看看