[ABC274Ex] XOR Sum of Arrays

section>

Problem Statement

For sequences $B=(B_1,B_2,\dots,B_M)$ and $C=(C_1,C_2,\dots,C_M)$, each of length $M$, consisting of non-negative integers, let the XOR sum $S(B,C)$ of $B$ and $C$ be defined as the sequence $(B_1\oplus C_1, B_2\oplus C_2, ..., B_{M}\oplus C_{M})$ of length $M$ consisting of non-negative integers. Here, $\oplus$ represents bitwise XOR.
For instance, if $B = (1, 2, 3)$ and $C = (3, 5, 7)$, we have $S(B, C) = (1\oplus 3, 2\oplus 5, 3\oplus 7) = (2, 7, 4)$.

You are given a sequence $A = (A_1, A_2, \dots, A_N)$ of non-negative integers. Let $A(i, j)$ denote the contiguous subsequence composed of the $i$-th through $j$-th elements of $A$.
You will be given $Q$ queries explained below and asked to process all of them.

Each query gives you integers $a$, $b$, $c$, $d$, $e$, and $f$, each between $1$ and $N$, inclusive. These integers satisfy $a \leq b$, $c \leq d$, $e \leq f$, and $b-a=d-c$. If $S(A(a, b), A(c, d))$ is strictly lexicographically smaller than $A(e, f)$, print Yes; otherwise, print No.

What is bitwise XOR? The exclusive logical sum $a \oplus b$ of two integers $a$ and $b$ is defined as follows.
  • The $2^k$'s place ($k \geq 0$) in the binary notation of $a \oplus b$ is $1$ if exactly one of the $2^k$'s places in the binary notation of $a$ and $b$ is $1$; otherwise, it is $0$.
For example, $3 \oplus 5 = 6$ (In binary notation: $011 \oplus 101 = 110$).
What is lexicographical order on sequences?

A sequence $A = (A_1, \ldots, A_{|A|})$ is said to be strictly lexicographically smaller than a sequence $B = (B_1, \ldots, B_{|B|})$ if and only if 1. or 2. below is satisfied.

  1. $|A|<|B|$ and $(A_{1},\ldots,A_{|A|}) = (B_1,\ldots,B_{|A|})$.
  2. There is an integer $1\leq i\leq \min\{|A|,|B|\}$ that satisfies both of the following.
    • $(A_{1},\ldots,A_{i-1}) = (B_1,\ldots,B_{i-1})$.
    • $A_i < B_i$.

Constraints

  • $1 \leq N \leq 5 \times 10^5$
  • $0 \leq A_i \leq 10^{18}$
  • $1 \leq Q \leq 5 \times 10^4$
  • $1 \leq a \leq b \leq N$
  • $1 \leq c \leq d \leq N$
  • $1 \leq e \leq f \leq N$
  • $b - a = d - c$
  • All values in the input are integers.

Input

The input is given from Standard Input in the following format, where $\text{query}_i$ represents the $i$-th query:

$N$ $Q$
$A_1$ $A_2$ $\dots$ $A_N$
$\text{query}_1$
$\text{query}_2$
$\vdots$
$\text{query}_Q$

The queries are in the following format:

$a$ $b$ $c$ $d$ $e$ $f$

Output

Print $Q$ lines. The $i$-th line should contain the answer to the $i$-th query.


Sample Input 1

4 5
1 2 3 1
1 3 2 4 1 4
1 2 2 3 3 4
1 1 2 2 3 4
1 2 2 3 3 3
1 4 1 4 1 1

Sample Output 1

No
No
Yes
No
Yes

For the first query, we have $A(1, 3) = (1, 2, 3)$ and $A(2, 4) = (2, 3, 1)$, so $S(A(1,3),A(2,4)) = (1 \oplus 2, 2 \oplus 3, 3 \oplus 1) = (3, 1, 2)$. This is lexicographcially larger than $A(1, 4) = (1, 2, 3, 1)$, so the answer is No.
For the second query, we have $S(A(1,2),A(2,3)) = (3, 1)$ and $A(3,4) = (3, 1)$, which are equal, so the answer is No.


Sample Input 2

10 10
725560240 9175925348 9627229768 7408031479 623321125 4845892509 8712345300 1026746010 4844359340 2169008582
5 6 5 6 2 6
5 6 1 2 1 1
3 8 3 8 1 6
5 10 1 6 1 7
3 4 1 2 5 5
7 10 4 7 2 3
3 6 1 4 7 9
4 5 3 4 8 9
2 6 1 5 5 8
4 8 1 5 1 9

Sample Output 2

Yes
Yes
Yes
Yes
No
No
No
No
No
No

很明显,是哈希的题。要判断哪个字典序大,可以通过二分找到第一个 \(i\) 使 \(a_i\ne b_i\) 然后判断 \(a_i\)\(b_i\) 的大小。然后二分过程中只需要判断两个序列是否相同,就可以用哈希判断。

官方题解的做法太神奇,这里参考了大多赛时AC程序的方法。

首先如果把异或改成加法,就是使用经典的 Robin-Karp 哈希。以一个数 \(x\) 作为位权,定义一个序列 \(a_1,a_2\cdots a_k\) 的哈希值为 \(x^{k-1}a_1+x^{k-2}a_2\cdots xa_{k-1}+a_{k}\) 这个 \(x\) 可以随机取。然后易得序列 \(a_1+b_1,a_2+b_2\cdots a_k+b_k\) 的哈希值就是 \(a\) 序列的哈希值加上 \(b\) 序列的哈希值。所以判断是否是否相同就可以直接将前两个的哈希值相加判断是否与第三个序列相同。

但是异或呢?如果是异或的话,我们的哈希就完全不行了,因为乘法对异或没有分配律。我们要找一种运算对异或满足分配律的,想到与和或,但是他们都不支持幂次。

这个运算是矩阵乘法。不妨把一个二进制当作一个行向量。众所周知,正常矩阵乘法的形式是 $$c_{i,j}=\sum{a_{i,j}\times b_{j,k}}$$

然后把他修改成 $$c_{i,j}=\bigoplus a_{i,j}\and b_{j,k}$$\(\bigoplus\) 仍然表示异或, \(\and\) 表示按位与。

根据矩阵的结论,由于按位与对异或有分配律,所以其实这样出来的矩阵具有结合律,对异或具有分配律。所以方法就是以一个随机01矩阵为位权。这样哈希时我们就可以直接将两个序列的哈希值异或起来,是与按位异或后的序列的哈希值相等。

但是这样一次矩阵乘法的复杂度是 \(log^3\),算上二分过不了?类似的以位运算为运算的矩阵乘法大多是可以压位的。观察上面的式子,如果 \(a_{i,j}=1,c_i^=b_j\)(c,b已经压成了二进制)。矩阵乘法复杂度降到 \(log^2\)

另外,由于矩阵满足分配律,所以可以预处理矩阵的幂后,可以像正常的哈希一样直接提取出区间 \([l,r]\) 的哈希值。但是我保险起见,打了一个倍增。这样更有可能对。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL; 
const int N=5e5+5,M=63;
mt19937_64 gen(time(0));
struct matrix{
	int a[M];
	void init()
	{
		for(int i=0;i<M;i++)
			a[i]=1LL<<i;
	}
	matrix operator*(const matrix&b)const{
		matrix c;
		memset(c.a,0,sizeof(c.a));
		for(int i=0;i<M;i++)
			for(int j=0;j<M;j++)
				if(a[i]>>j&1)
					c.a[i]^=b.a[j];
		return c;
	}
	void operator=(matrix b){
		for(int i=0;i<M;i++)
			a[i]=b.a[i];
	}
}pw[25]; 
LL mul(LL x,matrix a)
{
	LL ret=0;
	for(int i=0;i<M;i++)
		if(x>>i&1)
			ret^=a.a[i];
	return ret;
}
LL x[N],st[25][N];
int n,q,a,b,c,d,e,f;
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=0;i<M;i++)
		pw[0].a[i]=gen();
	for(int i=1;i<=n;i++)
		scanf("%lld",x+i),st[0][i]=x[i];
	for(int i=1;i<25;i++)
		pw[i]=pw[i-1]*pw[i-1];
	for(int i=1;i<25;i++)
		for(int j=1;j+(1<<i)-1<=n;j++)
			st[i][j]=st[i-1][j]^mul(st[i-1][j+(1<<i-1)],pw[i-1]);
	while(q--)
	{
		scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
		int l=0;
		for(int i=24;i>=0;i--)
			if(a+l+(1<<i)<=b+1&&e+l+(1<<i)<=f+1&&(st[i][a+l]^st[i][c+l])==st[i][e+l])
				l+=1<<i;
		if(e+l>f)
			printf("No\n");
		else if(a+l>b)
			printf("Yes\n");
		else if((x[a+l]^x[c+l])<x[e+l])
			printf("Yes\n");
		else
			printf("No\n");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值