1. 程式人生 > >【Codeforces Round 340 (Div 2)E】【莫隊演算法 真實區間思想】XOR and Favorite Number m組區間詢問 問區間中多少連續段異或值為k

【Codeforces Round 340 (Div 2)E】【莫隊演算法 真實區間思想】XOR and Favorite Number m組區間詢問 問區間中多少連續段異或值為k

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 numberkandaiof lengthn. Now he asks you to answermqueries. Each query is given by a pairliandriand asks you to count the number of pairs of integersiandj, such thatl ≤ i ≤ j ≤ rand the xor of the numbersai, ai + 1, ..., ajis equal tok.

Input

The first line of the input contains integersn

,mandk(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 containsnintegersai(0 ≤ ai ≤ 1 000 000) — Bob's array.

Thenmlines follow. Thei-th line contains integersliandri(1 ≤ li ≤ ri ≤ n) — the parameters of thei-th query.

Output

Printm

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 ofiandjfor 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 equals1for 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


*/