zoukankan      html  css  js  c++  java
  • LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)

    LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set



    $ solution: $

    这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小。于是我们分两部分贪心:(注意 $ tot $ 表示左右元素的异或和)

    1. 首先我们要让总和最大的话,我们只需要讨论 $ tot $ 的某一位为0的情况(如果为1,那么不管怎么分配两边的数都只能并且一定有一个数,使它这一位上含有1)。对于 $ tot $ 的某一位为0的情况,我们肯定贪心的让两边都在这一位上含有一!这个我们只需要让其中一个有一,另一个就必定有一。于是我们贪心的让 $ x2 $ 在这一位上尽量大
    2. 然后,我们要让左边最小,就只要再讨论 $ tot $ 的某一位为1的情况,我们肯定将这个1尽量分给 (x2) ,于是又是让 $ x2 $ 在这一位上尽量大!

    这两个贪心是有优先级的,必须第一个贪完,第二个再贪!然后构造 $ x2 $ 最大,线性基最擅长,为了满足优先级我们先在 $ tot $ 的某一位为0的位上跑线性基,再在 $ tot $ 的某一位为1的位上跑线性基!



    $ code: $

    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    
    #define ll long long
    #define db double
    #define rg register int
    
    using namespace std;
    
    int n;
    ll tot;
    ll a[100005];
    ll f[100005];
    ll p[100005];
    
    inline ll qr(){
    	register char ch; register bool sign=0; ll res=0;
    	while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    	while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    	if(sign)return -res; else return res;
    }
    
    inline void add(ll x){
    	for(rg i=60;i>=0;--i){ //第一优先级
    		if(!(tot&f[i])){ //先处理tot这一位为0的情况
    			if(x&f[i]){
    				if(p[i]) x^=p[i];
    				else{p[i]=x; return ;}
    			}
    		}
    	}
    	for(rg i=60;i>=0;--i){ //第二优先级
    		if(tot&f[i]){ //再处理tot这一位为1的情况
    			if(x&f[i]){
    				if(p[i]) x^=p[i];
    				else{p[i]=x; return ;}
    			}
    		}
    	}
    }
    
    inline ll ask(){
    	ll res=0;
    	for(rg i=60;i>=0;i--) //同理先保证全局最大
    		if(!(tot&f[i])&&!(res&f[i])) res^=p[i];
    	for(rg i=60;i>=0;i--) //然后保证单个最小(就是另一个最大)
    		if(tot&f[i]&&!(res&f[i])) res^=p[i];
    	return res;
    }
    
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	n=qr(); f[0]=1;
    	for(rg i=1;i<=60;++i) f[i]=f[i-1]<<1; //预处理
    	for(rg i=1;i<=n;++i) a[i]=qr(),tot^=a[i]; //读入,统计tot
    	for(rg i=1;i<=n;++i) add(a[i]); //逐个加入
    	printf("%lld
    ",tot^ask());
    	return 0;
    }
    
    
  • 相关阅读:
    svn command line tag
    MDbg.exe(.NET Framework 命令行调试程序)
    Microsoft Web Deployment Tool
    sql server CI
    VS 2010 One Click Deployment Issue “Application Validation did not succeed. Unable to continue”
    mshtml
    大厂程序员站错队被架空,只拿着五折工资!苟活和离职,如何选择?
    揭秘!Windows 为什么会蓝屏?微软程序员竟说是这个原因...
    喂!千万别忘了这个C语言知识!(~0 == -1 问题)
    Linux 比 Windows 更好,谁反对?我有13个赞成理由
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/11305992.html
Copyright © 2011-2022 走看看