zoukankan      html  css  js  c++  java
  • BZOJ4260,LOJ10051 Nikitosh 和异或

    题意

    给定一个含 (N) 个元素的数组 (A),下标从 (1) 开始。请找出下面式子的最大值:((A[l_1]igoplus A[l_1+1]igoplus …igoplus A[r_1])+ (A[l_2]igoplus A[l_2+1]^…igoplus A[r_2])),其中 (1le l_1le r_1<l_2le r_2le N,xigoplus y)表示 (x)(y) 的按位异或。

    对于 (100\%) 的数据,(2le N le 4 imes 10^5, 0le A_ile 10^9)

    分析

    参照qwerta的题解。

    首先记录异或前缀和s[i]=a[1]⊕a[2]⊕a[3]...⊕a[i]。

    设l[i]为以i结尾的区间中,异或值的最大值。

    因为异或有 x⊕x=0 的性质,所以区间 [l,r] 的异或值
    =a[l]⊕a[l+1]⊕...⊕a[r]
    =(a[1]⊕a[2]⊕a[3]...⊕a[l−1])⊕(a[1]⊕a[2]⊕a[3]...⊕a[r])
    =s[l−1]⊕s[r],

    所以求l[i],转化为找j<i,使得s[j]⊕s[i]最大。

    转化为「LOJ#10050」「一本通 2.3 例 2」The XOR Largest Pair(Trie

    以相似的方法可以求出r[i](以i开头的区间中,异或值的最大值)。

    时间复杂度:O(N log_2 A)。

    代码

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read()
    {
    	rg T data=0,w=1;
    	rg char ch=getchar();
    	while(!isdigit(ch))
    	{
    		if(ch=='-') w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))
    	{
    		data=data*10+ch-'0';
    		ch=getchar();
    	}
    	return data*w;
    }
    template<class T>il T read(rg T&x)
    {
    	return x=read<T>();
    }
    typedef long long ll;
    using namespace std;
    
    co int N=4e5+1;
    int a[N],l[N],r[N];
    int bin[31];
    void turn(int x)
    {
    	for(int i=0;i<31;++i,x>>=1)
    		bin[i]=x&1;
    }
    int tot,ch[N*31][2];
    int find()
    {
    	int u=0,res=0;
    	for(int i=30;i>=0;--i)
    	{
    		if(ch[u][bin[i]^1])
    			res+=(1<<i),u=ch[u][bin[i]^1];
    		else
    			u=ch[u][bin[i]];
    	}
    	return res;
    }
    void insert()
    {
    	int u=0;
    	for(int i=30;i>=0;--i)
    	{
    		if(!ch[u][bin[i]])
    			ch[u][bin[i]]=++tot;
    		u=ch[u][bin[i]];
    	}
    }
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	int n=read<int>();
    	for(int i=1;i<=n;++i)
    		read(a[i]);
    	int x=0;
    	for(int i=1;i<=n;++i)
    	{
    		x^=a[i];
    		turn(x);
    		insert();
    		l[i]=max(l[i-1],find());
    //		cerr<<i<<" l="<<l[i]<<endl;
    	}
    	x=0,tot=0;
    	memset(ch,0,sizeof ch);
    	for(int i=n;i>=1;--i)
    	{
    		x^=a[i];
    		turn(x);
    		insert();
    		r[i]=max(r[i+1],find());
    //		cerr<<i<<" r="<<r[i]<<endl;
    	}
    	ll ans=0;
    	for(int i=1;i<n;++i)
    		ans=max(ans,(ll)l[i]+r[i+1]);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    php 格利高里函数转化成时间戳
    图片转化成文件流
    下载文件(execl,img 等)
    项目开发流程
    大数据可以采用子查询
    文件上传接口
    多文件ajax 上传
    swoole 安装和简单实用
    jquery 滑动加载
    php实现分享到朋友圈,QQ,微博
  • 原文地址:https://www.cnblogs.com/autoint/p/10331434.html
Copyright © 2011-2022 走看看