• XOR UVALive


    UVALive - 8512 

    题意 :给出一个包含n个元素的数组A以及一个k,接下来进行q次询问,每次询问给出 l 和 r ,

    要你求出从A[l] , A[l+1] , A[l + 2],...,A[r]中任选出若干个数异或起来的值val,使得 k | val 最大,输出这个最大值。

    思路 :既然是要使得k | val得到的值最大,那么val必然是k这个数上二进制位为0的位置为1的数,同时1的位数要尽可能的多。

    这样我们就可以先对k取反,求出k二进制位为0的位数变成1的数p,再用A[i]与上p,将这些数放入线性基中。

    由于每次都是区间查询,我们就可以利用线段树的思想,建立一棵结点为线性基的线段树,

    每次区间查询的时候就查询出这几个区间合并后的线性基,再用线性基的性质查询最大值即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define maxn 12345
    ll t,n,k,q,l,r,a[maxn],ans;
    struct node
    {
        ll p[66];
        void init()
        {
            memset(p,0,sizeof(p));
        }
        node()
        {
            memset(p,0,sizeof(p));
        }
        void add(ll x)
        {
            for(int i=60; i>=0; i--)
            {
                if(!(x&(1<<i)))continue;
                if(!p[i])
                {
                    p[i]=x;
                    break;
                }
                else x^=p[i];
            }
        }
        node operator+(const node &b)const
        {
            node ret=b;
            for(int i=60; i>=0; i--)
                if(p[i])ret.add(p[i]);
            return ret;
        }
        ll rp()
        {
            ll re=0;
            for(int i=60; i>=0; i--)
                if((re^p[i])>re)re^=p[i];
            return re;
        }
    } tree[maxn*4];
    void up(int root)
    {
        tree[root]=tree[root*2]+tree[root*2+1];
    }
    void bulid(int root,int l,int r)
    {
        tree[root].init();
        if(l==r)
        {
            tree[root].add(a[l]);
            return ;
        }
        int mid=(l+r)/2;
        bulid(root*2,l,mid);
        bulid(root*2+1,mid+1,r);
        up(root);
    }
    node query(int root,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R)
            return tree[root];
        int mid=(l+r)/2;
        if(L>mid)return query(root*2+1,mid+1,r,L,R);
        else if(R<=mid)return query(root*2,l,mid,L,R);
        else return query(root*2,l,mid,L,R)+query(root*2+1,mid+1,r,L,R);
    }
    int main()
    {
        scanf("%lld",&t);
        while(t--)
        {
            scanf("%lld%lld%lld",&n,&q,&k);
            k=~k;
            for(int i=1; i<=n; i++)
            {
                scanf("%lld",&a[i]);
                a[i]=(a[i]&k);
            }
            k=~k;
            bulid(1,1,n);
            while(q--)
            {
                ans=k;
                scanf("%lld%lld",&l,&r);
                node tp=query(1,1,n,l,r);
                ans=(ans|tp.rp());
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    真正的Java学习从入门到精通
    Java学习从入门到精通(1) [转载]
    Java Learning Path(三)过程篇
    Java Learning Path(五)资源篇
    Java Learning Path(四) 方法篇
    浅析Java语言中两种异常的差别
    JDK,JRE,JVM区别与联系
    JAVA敏捷开发环境搭建
    谈谈WEB开发中的苦大难字符集问题
    java读取clob字段的几种方法
  • 原文地址:https://www.cnblogs.com/SDUTNING/p/10270263.html
Copyright © 2020-2023  润新知