zoukankan      html  css  js  c++  java
  • 2019牛客多校第四场B xor(线性基求交)题解

    题意:

    传送门

    (n)个集合,每个集合有一些数。给出(m)个询问,再给出(l)(r)和一个数(v),问你任意的(i in[l,r])的集合,能不能找出子集异或为(v)。简单点说,(v)能用([l,r])任意一个集合的子集异或和表示。

    思路:

    子集异或和显然是用线性基。我们用线段树维护任意区间的线性基交集即可。

    代码:

    /**
    求交集 O(logn * logn)
    **/
    LBasis intersection(const LBasis &a, const LBasis &b){
        LBasis ans, c = b, d = b;
        ans.init();
        for (int i = 0; i <= 32; i++){
            ll x = a.d[i];
            if(!x)continue;
            int j = i;
            ll T = 0;
            for(; j >= 0; --j){
                if((x >> j) & 1)
                    if(c.d[j]) {x ^= c.d[j]; T ^= d.d[j];}
                    else break;
            }
            if(!x) ans.d[i] = T;
            else {c.d[j] = x; d.d[j] = T;}
        }
        return ans;
    }
    
    #include<map>
    #include<set>
    #include<cmath>
    #include<cstdio>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    using namespace std;
    const int maxn = 50000 + 5;
    const int INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    using namespace std;
    
    struct LBasis{
        ll d[33];
        int tot;
        void init(){
            memset(d, 0, sizeof(d));
            tot = 0;
        }
        bool insert(ll x){
            for(int i = 32; i >= 0; i--){
                if(x & (1LL << i)){
                    if(d[i]) x ^= d[i];
                    else{
                        d[i] = x;
                        return true;
                    }
                }
            }
            return false;
        }
    
        bool checkin(ll x){
            for(int i = 32; i >= 0; i--){
                if(x & (1LL << i)){
                    if(d[i]) x ^= d[i];
                    else return false;
                }
            }
            return true;
        }
    
    };
    LBasis intersection(const LBasis &a, const LBasis &b){
        LBasis ans, c = b, d = b;
        ans.init();
        for (int i = 0; i <= 32; i++){
            ll x = a.d[i];
            if(!x)continue;
            int j = i;
            ll T = 0;
            for(; j >= 0; --j){
                if((x >> j) & 1)
                    if(c.d[j]) {x ^= c.d[j]; T ^= d.d[j];}
                    else break;
            }
            if(!x) ans.d[i] = T;
            else {c.d[j] = x; d.d[j] = T;}
        }
        return ans;
    }
    LBasis node[maxn << 2];
    void pushup(int rt){
        node[rt] = intersection(node[rt << 1], node[rt << 1 | 1]);
    }
    void build(int l, int r, int rt){
        if(l == r){
            int sz;
            scanf("%d", &sz);
            node[rt].init();
            while(sz--){
                ll x;
                scanf("%lld", &x);
                node[rt].insert(x);
            }
            return;
        }
        int m = (l + r) >> 1;
        build(l, m, rt << 1);
        build(m + 1, r, rt << 1 | 1);
        pushup(rt);
    }
    bool query(int L, int R, int l, int r, ll v, int rt){
        if(L <= l && R >= r){
            return node[rt].checkin(v);
        }
        int m = (l + r) >> 1;
        bool ok = true;
        if(L <= m)
            ok = ok && query(L, R, l, m, v, rt << 1);
        if(R > m)
            ok = ok && query(L, R, m + 1, r, v, rt << 1 | 1);
        return ok;
    }
    int main(){
        int n, m;
        scanf("%d%d", &n, &m);
        build(1, n, 1);
        while(m--){
            int l, r;
            ll x;
            scanf("%d%d%lld", &l, &r, &x);
            if(query(l, r, 1, n, x, 1)) printf("YES
    ");
            else printf("NO
    ");
        }
        return 0;
    }
    
    
  • 相关阅读:
    Struts2框架(二)
    Struts2框架(一)
    jsp定义全局的错误处理
    BeanUtils的使用、Java中的路径问题
    IntelliJ IDEA 14.1.4(Window)快捷键
    Log4J日志组件
    注解
    反射
    泛型
    AndroidStudio开发工具快捷键(转)
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11289022.html
Copyright © 2011-2022 走看看