Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum (树状数组维护异或值) ★ ★

来源:互联网 发布:淘宝客服主要做什么 编辑:程序博客网 时间:2024/05/17 18:12

题目大意:

给一大堆数字,问[L,R]区间,数字出现偶数次的数字,全部XOR起来的结果。

比如区间内数字有【1,2,3,3,2,1,1】

1出现3次

2出现2次

3出现2次

结果就是2 xor 3,这两个数字出线的次数是偶数次。

题解:

显然,区间【所有数字,可以重复出现】直接xor起来的结果,相当于xor了出现奇数次的数字。

如果区间所有数字,每个【数字只选一个】全部xor起来的结果,再xor上奇数次的结果,就是答案了。

第一问简单解决。第二问,可以离线,用树状数组维护一下就行了

#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <cstdlib>#include <algorithm>#include <cmath>#include <set>#include <map>#include <vector>using namespace std;const int maxn = 1000005;#define inf 0x3f3f3f3fint n,m;int a[maxn],ans[maxn],sum[maxn];vector<pair<int,int> > tmp[maxn];int c[maxn];map<int,int> mp;void update(int x,int val){    for(int i = x; i <= n; i += i&(-i))        c[i] ^= val;}int get_val(int x){    int ret = 0;    while(x)    {        ret ^= c[x];        x -= x & (-x);    }    return ret;}int main(){    int T;    //scanf("%d",&t);    while(scanf("%d",&n) != EOF)    {        memset(c,0,sizeof(c));        sum[0] = 0;        for(int i = 1; i <= n; i++)        {            scanf("%d",&a[i]);            sum[i] = sum[i-1] ^ a[i];            tmp[i].clear();        }        scanf("%d",&m);        for(int i = 0; i < m; i++)        {            int x,y;            scanf("%d%d",&x,&y);            tmp[y].push_back(make_pair(i,x));        }        mp.clear();        for(int i = 1; i <= n; i++)        {            if(mp.count(a[i]))                update(mp[a[i]],a[i]);            mp[a[i]] = i;            update(i,a[i]);            for(int j = 0; j < tmp[i].size(); j++)            {                int pos = tmp[i][j].first;                int pre = tmp[i][j].second;                ans[pos] = sum[pre-1] ^ sum[i];                ans[pos] ^= get_val(i) ^ get_val(pre-1);            }        }        for(int i = 0; i < m; i++)            printf("%d\n",ans[i]);    }    return 0;}


0 0
原创粉丝点击