线性基

虽然说原理不是贪心,但是实现起来很贪心?

一个线性基满足,对于它所表示的所有数的集合S,
S中任意多个数异或所得的结果均能表示为线性基中的元素互相异或的结果,即意,线性基能使用异或运算来表示原数集使用异或运算能表示的所有数。运用这个性质,我们可以极大地缩小异或操作所需的查询次数。
线性基合并也很简单,就是有值就试一下,但是这个操作的复杂度就是\(O(log^2n)\)

#include<bits/stdc++.h>
#define int long long
#define F(i,i0,n) for(int i=(i0);i<=(n);++i)
#define DF(i,i0,n) for(int i=(i0);i>=(n);--i)
#define pii pair<int,int>
#define fr first
#define sc second
using namespace std;
inline int rd(){
    int f=0,x=0;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
    return f?-x:x;
}
const int N=1e5+5;
struct LB{
	int p[61],flag;//能否表示0 
	void clear(){memset(p,0,sizeof(p));}
	LB(){clear();}
	void ins(int x){
	    DF(i,60,0)
	        if(x&(1ll<<i))
	            if(!p[i]){p[i]=x;break;}
	            else x^=p[i];   
	    flag=1;
	}
	void ins(const LB &x){
		DF(i,60,0)
			if(x.p[i])ins(x.p[i]);
	}
	bool chk(int x){
	    DF(i,60,0)
	        if(x&(1ll<<i))
	            if(!p[i])return 0;
	            else x^=p[i];
	    return 1;
	}
	int que_max(){
	    int ans=0;
	    DF(i,60,0)ans=max(ans,ans^p[i]);
	    return ans;
	}
	int que_min(){
	    if(!flag)return 0;
	    F(i,0,60)if(p[i])return p[i];
	}
	int tmp[N];
	int kth(int k){
	    int ans=0,cnt=0;
	    k-=flag;if(!k)return 0;
	    F(i,0,60){//重构线性基
	        DF(j,i-1,0)
	            if(p[i]&(1ll<<j))p[i]^=p[j];
	        if(p[i])tmp[cnt++]=p[i];
	    }
	    if(k>=(1ll<<cnt))return -1;
	    F(i,0,cnt-1)
	        if(k&(1ll<<i))ans^=tmp[i]; 
	    return ans;
	}
}lb;
int n;
signed main(){
    n=rd();
    F(i,1,n){
        int x=rd();
        lb.ins(x);
    }
    cout<<lb.que_max()<<'\n';
    return 0;
}

posted @ 2023-09-09 17:10  ussumer  阅读(25)  评论(0)    收藏  举报