线性基个人模板(常见操作全)

前缀线性基(查询区间内异或最大值)

struct PrefixLinearBasis{
    int d[maxn][32];//前缀线性基
    int pos[maxn][32];//最后一个修改i这个位置的数
    int cnt;
    PrefixLinearBasis(){
        memset(d,0,sizeof(d));
        memset(pos,0,sizeof(pos));
        cnt = 0;
    }
    void add(int x){//向线性基中添加x
        cnt ++;
        for(int i = 0; i < 32; i++){//复制前cnt-1个线性基
            d[cnt][i] = d[cnt - 1][i];
            pos[cnt][i] = pos[cnt - 1][i];
        }
 
        int P = cnt;
        for(int i = 31; i >= 0; i--){
            if((x >> i) & 1){
                if(d[cnt][i]){//插入失败
                    if(pos[cnt][i] < P){//交换位置
                        swap(pos[cnt][i],P);
                        swap(d[cnt][i],x);
                    }
                    x ^= d[cnt][i];//异或
                }
                else{//插入成功
                    d[cnt][i] = x;
                    pos[cnt][i] = P;
                    break;
                }
            }
        }
    }
    int queryMax(int l,int r){//查询[l,r]中的最大值
        int res = 0;
        for (int i = 31; i >= 0; i--){
            if(pos[r][i] < l) 
                continue;
            if ((res ^ d[r][i]) > res) 
                res ^= d[r][i];
        }
        return res;
    }
    int queryMin(int l,int r) {//查询[l,r]中的最小值
        for(int i = 0; i <= 60; i++){
            if(pos[r][i] < l)
                continue;
            if(d[r][i])
                return d[r][i];
        }
        return 0;
    }
}PLB;

线性基(最小值、最大值、k大值、合并、插入)(未测试)

struct LinearBasis{
    int p[32];
    int cnt;
    bool flag = false;
    LinearBasis(){
        memset(p,0,sizeof p);
        cnt = 0;
    }
    void insert(int x){
        if (x){
            for(int i = 31;i >= 0;i --){
                if (!(x >> i & 1)) continue;
                if (!p[i]) {
                    p[i] = x;
                    cnt ++;
                    return;
                }
                else x ^= p[i];
            }
        }
        flag = true;
    }
    void rebuild(){
        for(int i = 31;i >= 0;i --){
            for(int j = i - 1;j >= 0;j --){
                if (p[i] >> j & 1) p[i] ^= p[j];
            }
        }
    }
    long long query_kth(int x){
        if (x >= (1ll << cnt)) return -1;
        long long ans = 0;
        for(int i = 60;i >= 0;i --){
            if (x >> i & 1) ans ^= p[i];
        }
        return ans;
    }

    long long query_max(){
        long long ans = 0;
        for(int i = 31;i >= 0;i --){
            if ((ans ^ p[i]) > ans) ans ^= p[i];
        }
        return ans;
    }
    long long query_min(){
        if (!flag) return 0;
        for(int i = 0;i <= 31;i ++){
            if (p[i]) return p[i];
        }
    }
};
LinearBasis merge(LinearBasis a,LinearBasis b){
    for(int i = 31;i >= 0;i --){
        if (b.p[i]) a.insert(b.p[i]);
    }
    return a;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值