CodeForces 703D Mishka and Interesting sum (树状数组)

D. Mishka and Interesting sum

time limit per test: 3.5 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output

Description

Little Mishka enjoys programming. Since her birthday has just passed, her friends decided to present her with array of non-negative integers a1, a2, …, an of n elements!

Mishka loved the array and she instantly decided to determine its beauty value, but she is too little and can’t process large arrays. Right because of that she invited you to visit her and asked you to process m queries.

Each query is processed in the following way:

  1. Two integers l and r (1 ≤ l ≤ r ≤ n) are specified — bounds of query segment.
  2. Integers, presented in array segment [l,  r] (in sequence of integers a**l, a**l + 1, …, a**r) even number of times, are written down.
  3. XOR-sum of written down integers is calculated, and this value is the answer for a query. Formally, if integers written down in point 2 are x1, x2, …, x**k, then Mishka wants to know the value img, where img — operator of exclusive bitwise OR.

Since only the little bears know the definition of array beauty, all you are to do is to answer each of queries presented.

Input

The first line of the input contains single integer n (1 ≤ n ≤ 1 000 000) — the number of elements in the array.

The second line of the input contains n integers a1, a2, …, a**n (1 ≤ a**i ≤ 109) — array elements.

The third line of the input contains single integer m (1 ≤ m ≤ 1 000 000) — the number of queries.

Each of the next m lines describes corresponding query by a pair of integers l and r (1 ≤ l ≤ r ≤ n) — the bounds of query segment.

Output

Print m non-negative integers — the answers for the queries in the order they appear in the input.

Examples

input

1
2
3
4
3
3 7 8
1
1 3

output

1
0

input

1
2
3
4
5
6
7
8
7
1 2 1 3 3 2 3
5
4 7
4 5
1 3
1 7
1 5

output

1
2
3
4
5
0
3
1
3
2

Note

In the second sample:

There is no integers in the segment of the first query, presented even number of times in the segment — the answer is 0.

In the second query there is only integer 3 is presented even number of times — the answer is 3.

In the third query only integer 1 is written down — the answer is 1.

In the fourth query all array elements are considered. Only 1 and 2 are presented there even number of times. The answer is img.

In the fifth query 1 and 3 are written down. The answer is img.

Solution

题意

给你一个数组,若干个询问。询问区间 [l, r] 上出个次数为偶数的数的异或和。

思路

一个数字,奇数次异或和为其本身,偶数次异或和为 0。一个区间上所有数字异或和为该区间上出现奇数次的数字的异或和。而现在让我们求偶数次数字的异或和, 我们可以再求得区间上所有 distinct 数字 (去重) 的异或和,再用此异或和和区间所有数字异或和进行异或操作,即为所求。

对于区间所有数字的异或和,我们可以先预处理出一个前缀异或和 $sum$,区间 $[l,r]$ 上所有数字的异或和即为 sum[r] ^ sum[l-1]

区间上 distinct 数字的异或和我们用树状数组来维护。用一个 map 来维护某个数上次出现的位置,离线处理答案,走到 $a [i]$ 时,如果 $map [ a [i] ]$ 不为 0,(说明 $a [i] $ 之前出现过), 那么从上次的位置开始把 $a [i]$ 异或掉,并在此位置开始异或上 $a [i]$,更新 map。只把出现多次的值放在最后出现的位置(这个思想很常见)

询问按区间右端点排序,依此顺序回答。

AC 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <utility>
#include <algorithm>
#define INF 0x3f3f3f3f
#define DEBUG
#define DataIn
typedef long long LL;

using namespace std;
const int MAXN = 1e6+10;

int n, q;
int a[MAXN], sum[MAXN], tree[MAXN<<2]; //sum为原数组前缀和
map<int, int> mp; //mp[i]表示上一次i出现的下标

struct node
{
int l, r;
int no;
int ans;
}Query[MAXN];

bool cmp(node a, node b)
{
return a.r==b.r ? a.l<b.l : a.r<b.r;
}

bool cmp2(node a, node b)
{
return a.no < b.no;
}

int lowbit(int k)
{
return k&(-k);
}

void update(int ind, int val)
{
while(ind <= n)
{
tree[ind] ^= val;
ind += lowbit(ind);
}
}

int query(int k)
{
int ans = 0;
while(k)
{
ans ^= tree[k];
k -= lowbit(k);
}
return ans;
}

int main()
{
scanf("%d", &n);
for(int i=0; i<n; i++)
scanf("%d", a+i);

scanf("%d", &q);
for(int i=0; i<q; i++)
{
scanf("%d%d", &Query[i].l, &Query[i].r);
Query[i].no = i;
}

sum[0] = a[0];
for(int i=1; i<n; i++)
sum[i] ^= sum[i-1];

sort(Query, Query+q, cmp);
int p = 0;
for(int i=0; i<q; i++)
{
int l=Query[i].l, r=Query[i].r;
while(p<=r)
{
if(mp[a[p]] == 0)
{
mp[a[p]] = p;
update(p, a[p]);
}
else
{
update(mp[a[p]], a[p]); //从上次的位置开始把 a[i] 异或掉
update(p, a[p]); //在此位置开始异或上 a[i]
mp[a[p]] = p;
}
p++;
}
Query[i].ans = sum[r] ^ sum[l-1] ^ query(r) ^ query(l-1);
}

sort(Query, Query+q, cmp2);
for(int i=0; i<q; i++)
printf("%d\n", Query[i].ans);
return 0;
}