XOR UVALive - 8512(线性基)

ACM-ICPC 2017 Asia Xi’an
A. XOR ACM-ICPC 2017 Asia Xi’an
题意:给定N个数和Q个询问,每次在[L,R]区间内取一些数,使得与K异或的值最大,问这个值时多少
思路:与K异或使得结果变大,从二进制的角度考虑,就是把k的二进制中为0的位置尽量变为1。所以先将K取反,对A[i]&K,建立线性基,最后取最大值

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define ll long long
using namespace std;
const int maxn=1e5+10,INF=0x3f3f3f3f;
const int mod=1e9+7;

ll t,N,Q,K;
ll a[maxn];

struct LinearBase
{
    ll base[66];
    int cnt;
    LinearBase()
    {
        memset(base,0,sizeof(base));
        cnt=0;
    }
    
    void init()
    {
        memset(base,0,sizeof(base));
        cnt=0;    	
    }
 
    bool Insert(ll x)
    {
        for(int i=60;i>=0;--i)
        {
            if(x&(1ll<<i))
            {
                if(!base[i])
                {
                    base[i]=x;
                    break;
                }
                x^=base[i];
            }
        }
        return x>0;
    }
    	
    
	ll QueryMax()
	{
		ll ret=0;
		for(int i=60;i>=0;--i)
			if((ret^base[i])>ret)
				ret^=base[i];
		return ret;
	}		
	
	ll QueryMin()
	{
		for(int i=0;i<=60;++i)
			if(base[i])
				return base[i];
		return 0;
	}
     
 
    bool find(ll x)
    {
        for(int i=32;i>=0;--i)
        {
            if(x&(1ll<<i))       
            {
                if(!base[i])
                    break;
                x^=base[i];
            }  
        }
        return x==0;
    }      
}ST[maxn<<2];

LinearBase Merge(const LinearBase &a,const LinearBase &b)
{
	LinearBase ret=a;
	for(int i=60;i>=0;--i)
		if(b.base[i])
			ret.Insert(b.base[i]);
	return ret;
}	

void Push_up(int rt)
{
	ST[rt]=Merge(ST[ls],ST[rs]);
}

void Build(int rt,int L,int R)
{
	ST[rt].init();
	if(L==R)
	{
		ST[rt].Insert(a[L]);
		return;
	}
	int mid=(L+R)>>1;
	Build(ls,L,mid);
	Build(rs,mid+1,R);
	Push_up(rt); 
}

LinearBase Query(int rt,int l,int r,int L,int R)
{
	if(l<=L&&R<=r)
		return ST[rt];
	int mid=(L+R)/2;	
	if(r<=mid)
		return Query(ls,l,r,L,mid);
	else if(l>mid)
		return Query(rs,l,r,mid+1,R);
	else
		return Merge(Query(ls,l,r,L,mid),Query(rs,l,r,mid+1,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;
		Build(1,1,N);
		
		
		while(Q--)
		{
			int l,r;
			scanf("%d%d",&l,&r);
			LinearBase lb=Query(1,l,r,1,N);
			ll ans=lb.QueryMax();
			printf("%lld\n",(ans|K));
		}	
	}
	return 0;
}
/*
1
5 3 0
1 2 3 4 5
1 3
2 4
3 5
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值