Xor Submatrix(Trie树)

Xor Submatrix

Time limit: 
2000 ms

Memory limit: 
512 MB

Given an array VV of size NN and another array UU of size MM, we build a matrix AA of size N \times MN×M, where A_{i, j} = V_i\ \text{xor}\ U_jAi,j=Vi xor Uj.

We say the score of a submatrix of AA is the xor sum of all its elements. Find the submatrix with the highest score.

Standard input

The first line contains two integers NN and MM.

The second line contains NN integers representing the elements of VV.

The thirst line contains MM integers representing the elements of UU.

Standard output

Print the highest possible score on the first line.

Constraints and notes

  • 1 \leq N, M \leq 10001N,M1000 
  • 0 \leq V_i < 2^{29}0Vi<229 
  • 0 \leq U_i < 2^{29}0Ui<229 
InputOutputExplanation
3 4
5 3 1
2 1 2 4
7

《Xor Submatrix(Trie树)》

3 3
10 12 4
5 10 9
15

《Xor Submatrix(Trie树)》

3 3
1 2 1
4 2 8
15

《Xor Submatrix(Trie树)》

题意:给你两个序列V跟U,构造一个矩阵A,其中Aij = Ui ^ Vj

求最大的子矩阵的异或和。

思路:根据异或的特性,很容易想到跟奇偶有关,所以可以将子矩阵分成四种情况讨论:

《Xor Submatrix(Trie树)》

偶数 * 偶数:序列U跟V的每个数都被异或了偶数次,故结果恒为0.

偶数 * 奇数:序列V的每个数都被异或了偶数次,故只需计算计算序列U中长度为偶数的异或和情况。

奇数 * 偶数:序列U的每个数都被异或了偶数次,故只需计算计算序列V中长度为偶数的异或和情况。

奇数 * 奇数:序列U跟V中长度为奇数的所有情况的异或,这个不能暴力处理,可以先将U序列或者V

                    序列的 长度为奇数的的异或和插入到Trie树中,再分析另一个序列中长度为奇数的异或

                    和与另一序列异或得到的最大值。相当于求:一个数与一个另一个序列的最大异或和。

                    时间复杂度为O(n * n * logn) 

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace	std;
const int maxn = 10000000;
struct Trie
{
	int next[maxn][2];
	int root;
	void init()
	{
		memset(next,-1,sizeof next);
		root = 0;
	}
	void insert(int x)
	{
		int now = 0;
		for(int i=31;i>=0;i--)
		{
			if(x&(1<<i))
			{
				if(next[now][1]>=0) now = next[now][1];
				else 
				{
					next[now][1] = ++root;
					now = next[now][1];
				}
			}
			else 
			{
				if(next[now][0]>0) now = next[now][0];
				else 
				{
					next[now][0] = ++root;
					now = next[now][0];
				}
			}
		}
	}

	int query(int x)
	{
		int res = 0,now = 0;
		for(int i=31;i>=0;i--)
		{
			int tmp = x&(1<<i);
			if(next[now][!tmp]>=0)
			{
				res |= (1<<i);
				now = next[now][!tmp];
			}
			else now = next[now][tmp];
		}
		return res;
	}
};
Trie ac;
int a[1010],b[1010];
int prea[1010],preb[1010];
int main()
{
	
	int n,m; scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) 
		scanf("%d",&a[i]),prea[i] = prea[i-1]^a[i];
	for(int i=1;i<=m;i++) 
		scanf("%d",&b[i]),preb[i] = preb[i-1]^b[i];
	int res = 0;
	for(int i=1;i<=n;i++)
		for(int j=2;i+j-1<=n;j+=2) res = max(res,prea[i+j-1]^prea[i-1]); 
	for(int i=1;i<=m;i++)
		for(int j=2;i+j-1<=m;j+=2) res = max(res,preb[i+j-1]^preb[i-1]);
	ac.init();
	for(int i=1;i<=n;i++)
		for(int j=1;i+j-1<=n;j+=2) ac.insert(prea[i+j-1]^prea[i-1]);
	for(int i=1;i<=m;i++)
		for(int j=1;i+j-1<=m;j+=2) res = max(res,ac.query(preb[i+j-1]^preb[i-1]));
	printf("%d\n",res);
}

    原文作者:Trie树
    原文地址: https://blog.csdn.net/weixin_34196559/article/details/79801691
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞