CodeForces - 617E. XOR and Favorite Number

题意:

给定一个长度为 n 的数组 a 和一个数字 k,有 m 次询问,每次询问区间 [ l, r ] 中满足有多少个二元组 ( i, j ) 满足 l <= i <= j <= r 且 x = i j a x = k \oplus_{x=i}^{j}a_x = k 。(n, m <= 1e5, k, ai <= 1e6)

链接:

https://vjudge.net/problem/CodeForces-617E

解题思路:

对于区间连续异或和,令 b 0 = 0 b_0 = 0 , b i = b i 1 + a i b_i = b_{i-1} + a_i , 则条件转化为求有多少个二元组( i, j ) 满足 l - 1 <= i < j <= r 且 a[ i ] ^ a[ j ] = k,注意 i ≠ j,即元素不为空,然后用莫队转移答案即可。

参考代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define sz(a) ((int)a.size())
#define mem(a, b) memset(a, b, sizeof a)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int maxm = 5e2 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

int id[maxn];
struct Qr{
	int l, r, p;
	bool operator < (const Qr &o) const{
		return id[l] == id[o.l] ? (id[l] & 1 ? r > o.r : r < o.r) : id[l] < id[o.l];
	}
} qr[maxn];
int a[maxn], sum[1 << 21];
ll ans[maxn], ret;
int n, m, k;

void add(int x){

	ret += sum[x ^ k];
	++sum[x];
}

void del(int x){

	--sum[x];
	ret -= sum[x ^ k];
}

int main(){

//	ios::sync_with_stdio(0); cin.tie(0);
	scanf("%d%d%d", &n, &m, &k);
	for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for(int i = 1; i <= n; ++i) a[i] ^= a[i - 1];
	for(int i = 1; i <= m; ++i){

		int l, r; scanf("%d%d", &l, &r);
		qr[i] = { l, r, i };
	}
	int len = sqrt(n);
	for(int i = 1; i <= n; ++i) id[i] = (i - 1) / len + 1;
	int l = 1, r = 0;
	sort(qr + 1, qr + 1 + m);
	for(int i = 1; i <= m; ++i){

		--qr[i].l;
		while(l > qr[i].l) --l, add(a[l]);
		while(r < qr[i].r) ++r, add(a[r]);
		while(l < qr[i].l) del(a[l]), ++l;
		while(r > qr[i].r) del(a[r]), --r;
		ans[qr[i].p] = ret;
	}
	for(int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
	return 0;
}
发布了55 篇原创文章 · 获赞 0 · 访问量 1278

猜你喜欢

转载自blog.csdn.net/weixin_44059127/article/details/101001600
今日推荐