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

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 al, al + 1, ..., ar)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, ..., xk, then Mishka wants to know the value , where  — 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, ..., an (1 ≤ ai ≤ 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
3
3 7 8
1
1 3
output
0
input
7
1 2 1 3 3 2 3
5
4 7
4 5
1 3
1 7
1 5
output
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 .

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


题意:给出一个长度为n序列,进行m次询问,询问内容为区间[l,r]内出现次数为偶数的数的xor和。

分析:区间内直接进行xor和就等价于区间内出现次数为奇数的数的xor和,设这个和为s1,询问的和为s2,那么x1^x2为区间内所有出现的不同的数(所有的数出现次数不是奇数就是偶数)的xor和。

考虑使用一个树状数组来进行区间内“不同的数”的统计。对于序列从左向右进行更新,设更新到第i位,将a[i]直接插入到树状数组中的i位置。用一个map统计a[i]是否出现过,如果出现过则清除掉树状数组中a[i]前一次出现的位置的数。

例如,对于序列1 2 1 2

更新结果依次为

1 0 0 0

1 2 0 0

0 2 1 0

0 0 1 2

这个更新结果代表了第i个位置之前,每个数字最后一次出现的位置。由于这个结果是存在树状数组中的,可以直接进行logn时间内的区间求xor和,区间xor和的内容即为该区间内出现的所有不同的数的xor和。在更新到第i位的时候直接求出区间右端点为i的询问的结果。


#include <iostream>
#include <vector>
#include <map>
#include <cstring>

using namespace std;

const int MaxN = 1000000 + 5;

#define L first
#define Qid second
map<int, int> pos;      //pos[i]存储值为i的元素第一次出现的位置
vector<pair<int, int>> q[MaxN];    //下标:右端点,first:左端点,second:询问的序号
vector<pair<int, int>>::iterator it;
int n, m, l, r, prevPos, appearXOR;
int a[MaxN];
int ans[MaxN];  //存储答案的数组
int PrefixSum[MaxN];       //前缀xor和
int Tree[MaxN]; //树状数组

inline int lowbit(int x) {
    return x & (-x);
}

inline void add(int x, int value) {    //树状数组单点更新
    for (int i = x; i <= MaxN; i += lowbit(i))
        Tree[i] ^= value;
}

inline int get(int x) {    //树状数组询问
    int sum = 0;
    for (int i = x; i; i -= lowbit(i))
        sum ^= Tree[i];
    return sum;
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    memset(Tree, 0, sizeof(Tree));
    memset(ans, 0, sizeof(ans));
    memset(a, 0, sizeof(a));
    memset(PrefixSum, 0, sizeof(PrefixSum));
    pos.clear();
    for (int i = 0; i < MaxN; i++) q[i].clear();

    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        PrefixSum[i] = PrefixSum[i - 1] ^ a[i];
    }
    cin >> m;
    for (int i = 1; i <= m; i++) {
        cin >> l >> r;
        q[r].push_back(make_pair(l, i));
    }
    for (int i = 1; i <= n; i++) {
        prevPos = pos[a[i]];    //a[i]这个数值前一次出现的位置
        if (prevPos != 0)
            add(prevPos, a[i]);
        add(i, a[i]);
        pos[a[i]] = i;
        for (it = q[i].begin(); it != q[i].end(); it++) {
            l = (*it).L;
            r = i;
            appearXOR = get(r) ^ get(l - 1);
            ans[(*it).Qid] = PrefixSum[l - 1] ^ PrefixSum[r] ^ appearXOR;
        }
    }
    for (int i = 1; i <= m; i++)
        cout << ans[i] << "\n";
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值