CF617E XOR and Favorite Number(普通莫队)

本文介绍了一种解决区间异或查询问题的高效算法。通过预处理异或前缀和,利用莫队算法离线处理多个查询,实现快速查找区间内异或结果等于特定值k的元素数量。文章详细解释了算法原理,并提供了C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

题目传送门
题意:给你一个大小为n的序列,然后给你一个数字k,再给出m组询问,询问给出一个区间,问这个区间里面有多少个区间的异或结果为k

题解

这是道sb题劝大家不要写

  • a [ i ] a[i] a[i] 1 1 1~ i i i区间的异或前缀和,那么区间 [ L , R ] [L,R] [L,R]的异或和为 a [ L − 1 ]   x o r   a [ R ] a[L-1] \ xor \ a[R] a[L1] xor a[R](异或的自反性)
  • 如果 a   x o r   b = c a \ xor \ b = c a xor b=c,那么 a   x o r   c = b a \ xor \ c = b a xor c=b
  • 知道了上面那个性质之后我们发现如果我们知道 a   x o r   k a \ xor \ k a xor k等于哪些数,我们就可以知道 a   x o r a \ xor a xor哪些数等于 k k k
  • f [ i ] f[i] f[i]表示数字 i i i出现的次数
  • 最后莫队离线维护一下即可(开数组时注意下数组大小)

code

#include <bits/stdc++.h> 
using namespace std; 
typedef long long LL; 
const int maxm = (1 << 20); 

template <typename T> 
inline void read(T &s) {
	s = 0; 
	T w = 1, ch = getchar(); 
	while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
	while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
	s *= w; 
}

LL n, m, k, ans; 
LL a[maxm], f[maxm], res[maxm], belong[maxm]; 
struct query { int l, r, id; } q[maxm]; 

inline bool cmp(query A, query B) {
	return belong[A.l] == belong[B.l] ? A.r < B.r : A.l < B.l; 
}

inline void add(int x) {
	ans += f[ a[x] ^ k]; 
	f[ a[x] ]++; 
}

inline void del(int x) {
	f[ a[x] ]--; 
	ans -= f[ a[x] ^ k ]; 
}

int main() {
	read(n); read(m); read(k); 
	int blo = n / sqrt(m); 
	for (int i = 1; i <= n; ++i) {
		read(a[i]); 
		a[i] ^= a[i - 1]; 
		belong[i] = (i - 1) / blo + 1; 
	}
	for (int i = 1; i <= m; ++i) {
		read(q[i].l), read(q[i].r); 
		q[i].id = i; 
	}
	sort(q + 1, q + m + 1, cmp); 
	
	f[0] = 1; 
	int l = 1, r = 0; 
	for (int i = 1; i <= m; ++i) {
		int ql = q[i].l, qr = q[i].r; 
		while (l < ql) { del(l - 1); ++l; }
		while (l > ql) { l--, add(l - 1); } 
		while (r < qr) add(++r); 
		while (r > qr) del(r--); 
		res[ q[i].id ] = ans; 
	}
	
	for (int i = 1; i <= m; ++i) 
		printf("%lld\n", res[i]); 
	return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值