zoukankan      html  css  js  c++  java
  • 2017icpc 西安 A.XOR

    2017icpc 西安 A.XOR

    题意:

    长度为(n)的数组,(q)次询问,每次询问给出(l,r),从([l,r])区间中选出一些数字使得这些数字的异或和或上(k)最大。

    思路:

    线性基是处理异或问题的好手,对于这种区间异或最大可以考虑用线段树维护线性基合并。

    考虑怎么样能有(k|(a_{i_1} xor a_{i_2} xor ,..., xor a_{i_m}))最大。

    最开始的想法是:搞出区间线性基,然后从高位一位一位的搜,如果(k)(1),那就不考虑线性基这一位,如果没有(1),就一定考虑,但是很快的就举出了反例。

    考虑(k)需要什么?

    (k)这一位有(1),我们可以尽量不管他,如果这一位没有(1),我们尽量从数字中选择把这位填上,实在没有就算了。

    所以对(k)取反,对于线段树每个节点插入(k&a(i)),每次询问查询([l,r])最大结果,最后最结果或上(k)

    正确性:

    当对(k)取反后,对(a(i))进行与运算,实际上就是在找(a(i))这一位有没有(1)

    同时也有可能将本来(a(i))(1)的地方给取反后的(k)搞掉了,这不用担心,因为最后对答案或上(k),就回来了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e4+10;
    
    int n, m, k, a[maxn];
    int l, r, ans;
    
    struct LineBase
    {
        int p[32];
        void init() {memset(p, 0, sizeof p);}
        void ins(int x)
        {
            for(int i = 30; i >= 0; i--)
            {
                if(x&(1<<i))
                {
                    if(!p[i])
                    {
                        p[i] = x;
                        return;
                    }
                    x ^= p[i];
                }
            }
        }
    
        int qmax()
        {
            int res = 0;
            for(int i = 30; i >= 0; i--)
                res = max(res, res^p[i]);
            return res;
        }
    };
    
    struct SegmentTree
    {
        int l, r;
        LineBase t;
        #define lson (p<<1)
        #define rson (p<<1|1)
        #define l(x) tree[x].l
        #define r(x) tree[x].r
        #define t(x) tree[x].t
    }tree[maxn<<2];
    
    LineBase merge_base(LineBase a, LineBase b)
    {
        for(int i = 30; i >= 0; i--)
            if(a.p[i]) b.ins(a.p[i]);
        return b;
    }
    
    void build(int p, int l, int r)
    {
        l(p) = l, r(p) = r;
        t(p).init();
        if(l == r)
        {
            t(p).ins(a[l]);
            return;
        }
        int mid = (l+r)>>1;
        build(lson, l, mid);
        build(rson, mid+1, r);
        t(p) = merge_base(t(lson), t(rson));
    }
    
    LineBase ask(int p, int l, int r)
    {
        if(l <= l(p) && r(p) <= r) return t(p);
        int mid = (l(p)+r(p))>>1;
        if(mid >= r) return ask(lson, l, r);
        else if(mid < l) return ask(rson, l, r);
        else return merge_base(ask(lson, l, r), ask(rson, l, r));
    }
    
    void solve()
    {
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            a[i] = a[i]&(~k);
        }
        build(1, 1, n);
        while(m--)
        {
            scanf("%d%d", &l, &r);
            LineBase tmp = ask(1, l, r);
            ans = tmp.qmax();
            ans = ans|k;
            printf("%d
    ", ans);
        }
    }
    
    int main()
    {
        int T; scanf("%d", &T);
        while(T--) solve();
        return 0;
    }
    
    
  • 相关阅读:
    2019-2020 20191232《信息安全专业导论》第七周学习总结
    求最大公约数伪代码
    2019-2020-1 20191232《信息安全专业导论》第五周学习总结
    2019-2020 20191232《信息安全专业导论》第二周学习总结
    冲刺分析
    冲刺第5天——json
    2020课程设计(基于gmssl的CA系统构建及应用)个人报告——20181211沈芮吉
    2020课程设计gmssl
    2020课程设计第三周任务——20181211沈芮吉
    2020课程设计第二周任务——20181211沈芮吉
  • 原文地址:https://www.cnblogs.com/zxytxdy/p/12543871.html
Copyright © 2011-2022 走看看