【Codeforces Round 340 (Div 2)E】【莫队算法 真实区间思想】XOR and Favorite Number m组区间询问 问区间中多少连续段异或值为k

原创 2016年02月28日 13:06:45

E. XOR and Favorite Number
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pair li and ri and asks you to count the number of pairs of integers i and j, such that l ≤ i ≤ j ≤ r and the xor of the numbers ai, ai + 1, ..., aj is equal to k.

Input

The first line of the input contains integers n, m and k (1 ≤ n, m ≤ 100 000, 0 ≤ k ≤ 1 000 000) — the length of the array, the number of queries and Bob's favorite number respectively.

The second line contains n integers ai (0 ≤ ai ≤ 1 000 000) — Bob's array.

Then m lines follow. The i-th line contains integers li and ri (1 ≤ li ≤ ri ≤ n) — the parameters of the i-th query.

Output

Print m lines, answer the queries in the order they appear in the input.

Examples
input
6 2 3
1 2 1 1 0 3
1 6
3 5
output
7
0
input
5 3 1
1 1 1 1 1
1 5
2 4
1 3
output
9
4
4
Note

In the first sample the suitable pairs of i and j for the first query are: (1, 2), (1, 4), (1, 5), (2, 3), (3, 6), (5, 6), (6, 6). Not a single of these pairs is suitable for the second query.

In the second sample xor equals 1 for all subarrays of an odd length.



#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 1e5+10, M = 1e5+10, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int n, m, k;
struct A
{
	int id;
	int o;
	int l, r;
	bool operator < (const A&b)const
	{
		if (id != b.id)return id < b.id;
		return r < b.r;
	}
}a[M];
LL ans[M];
int num[(int)1.05e6];
int c[N];
int ins(int p)
{
	int tmp = num[c[p] ^ k];
	++num[c[p]];
	return tmp;
}
int del(int p)
{
	--num[c[p]];
	int tmp = num[c[p] ^ k];
	return tmp;
}
int main()
{
	while (~scanf("%d%d%d", &n,&m,&k))
	{
		int len = sqrt(n);
		for (int i = 1; i <= n; ++i)
		{
			scanf("%d", &c[i]);
			c[i] ^= c[i - 1];
		}
		for (int i = 1; i <= m; ++i)
		{
			scanf("%d%d", &a[i].l, &a[i].r); --a[i].l;
			a[i].id = a[i].l / len;
			a[i].o = i;
		}
		sort(a + 1, a + m + 1);
		MS(num, 0);
		LL ANS = 0;
		int l = a[1].l;
		int r = a[1].l-1;

		for (int i = 1; i <= m; ++i)
		{
			while (l > a[i].l)ANS += ins(--l);
			while (r < a[i].r)ANS += ins(++r);
			while (l < a[i].l)ANS -= del(l++);
			while (r > a[i].r)ANS -= del(r--);
			ans[a[i].o] = ANS;
		}
		for (int i = 1; i <= m; ++i)printf("%lld\n", ans[i]);
	}
	return 0;
}
/*
【trick&&吐槽】
做题的心态千万要稳住。
1,检查是否爆int————不要只检验答案输出是lld还是d,所有定义也都要检查下
2,检查数组是否开小。这道题虽然数字的范围都是1e6,然而,异或之后还是可达2^20-1的。
	于是,数组还是要开到1<<20的
3,这题的异或是对区间

【题意】
给你n(1e5)个数,每个数的权值都在[0,1e6]之间。
有m(1e5)个询问,
对于每个询问,给定区间[l,r],问你区间内有多少个连续子段(按照题目定义,显然非空),
满足子段的连续异或和恰好为k(k是[0,1e6]范围的数)

【类型】
莫队算法
真是区间思想

【分析】
1,这题询问众多,而且询问都是[l,r]的形式。
我们显然想到使用莫队做。
2,涉及到区间连续异或和,我们想到用前缀和映射思想。
3,数字范围最大只有1e6,于是可以开差不多(其实要1<<20大小),做映射。

这题最关键的地方,在于,比如l=5,r=6,我们实际是可以需要用c[6]^c[4]来得到val[5]+val[6]
这里浪费了很多时间,并且想了很多复杂的方法。

然而,我们如果一旦发现到其真实区间,问题就变得轻而易举了!
我们发现,对于我们选定的一个区间段,比如l=5,r=5,其实是有两个位置的,5号位置前,5号位置后,位置的选择方式并不是r-l-1种,而是r-l种
于是,我们对于所有的查询区间[l,r],使得l--,使其变成其真实区间[l-1,r]。
然后,我们把所有前缀和x都用num[]数组计数,就可以更新答案了。

如果是区间扩展操作,在这个前缀和添加进去之间的num[x^k]就是对答案的增贡献,然后+=num[x]
如果是区间缩减操作,先-=num[x],然后在这个前缀和删除之后的num[x^k]就是对答案的减贡献。

为什么区间扩展操作先+=num[x^k]再把这个值加进去
而如果是区间缩减操作,则是把这个值删除,再-=num[x^k]

为什么这样子呢?为了防止x^k==x,即这个区间段和自身做匹配的情况发生。
自身与自身做匹配,说明选择的是空区间段。显然是不行的。

于是,一个左区间段-1对应到真实区间,一个加减顺序解决掉k==0的特殊情况,
用在一起这道题就可以AC啦。

【时间复杂度&&优化】
O(msqrt(n))

【数据】
5 4 0
0 0 0 0 0
1 5
3 3
5 5
2 4


*/


版权声明:题解中哪里写错请一定要指出来QwQ 转载还请注明下出处哦,谢谢^_^

相关文章推荐

n个数字中最多有多少不重叠的非空区间

问题 给出n个数字a_1,…,a_n,最多有多少不重叠的非空区间

noj 2107 有趣的区间异或值(异或,找规律)

有趣的区间异或值 时间限制(普通/Java) : 2000 MS/ 6000 MS          运行内存限制 : 65536 KByte 总提交 : 354            测试通...
  • acm_cxq
  • acm_cxq
  • 2016年08月20日 15:49
  • 2175

Codeforces 617E XOR and Favorite Number (区间异或和 莫队算法 分块暴力)

Codeforces 617E XOR and Favorite Number (区间异或和 莫队算法 分块暴力)

hdu 3915 Game 求N个数中取若干个数字使得它们的异或值为0的方法数 高斯消元(mod2)

Problem Description   Mr.Frost is a child who is too simple, sometimes naive, always plays some sim...

[cqbzoj]区间异或最大值 - USACO 奶牛异或

奶牛异或时间限制: 1 Sec 内存限制: 64 MB题目描述农民约翰在喂奶牛的时候被另一个问题卡住了。他的所有N(1 ...

连续子串最大最小异或值 Trie+Xor LightOJ 1269 Consecutive Sum

http://lightoj.com/volume_showproblem.php?problem=1269 题意: 给定一个序列,求选定一段区间的亦或和最大值和最小值。 解析: ...

[BZOJ2125][仙人掌]最短路

题意求仙人掌上的多元最短路考虑如果在树上,u,v两点之间的最短路为dis[u]+dis[v]-2*dis[lca]。因为仙人掌每个点只属于一个简单环,先dfs弄清仙人掌的结构,对于环把环中离根节点最近...
  • Coldef
  • Coldef
  • 2017年02月13日 08:22
  • 133

新 版 骗 分 导 论

新  版  骗  分  导  论 THE NEW GUIDE OF CHEATING IN INFORMATICS OLYMPIAD 蒟 蒻 的 宝 书 目录 第1章 绪论 第2章 从无解出...

Codeforces Round #340 (Div. 2) 617E XOR and Favorite Number 莫队算法

题意:给一段序列和一些l,r的询问 求l,r之间有多少个连续子序列的异或=k 思路: http://www.bilibili.com/video/av4291097/ORZ卿神#include ...

Codeforces Round #340 (Div. 2) E. XOR and Favorite Number(莫队算法)

题意: 给定N≤105个数的序列,Q≤105次询问,给定一个数K≤106给定N\le 10^5个数的序列, Q\le 10^5次询问, 给定一个数K\le 10^6 询问[L,R]中,满足i...
  • lwt36
  • lwt36
  • 2016年01月25日 23:28
  • 231
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【Codeforces Round 340 (Div 2)E】【莫队算法 真实区间思想】XOR and Favorite Number m组区间询问 问区间中多少连续段异或值为k
举报原因:
原因补充:

(最多只允许输入30个字)