题意:求区间内出现偶数次的数的异或值。
分析:和求一个区间内不同元素个数做法一样。树状数组存的是不同元素的前缀异或和。用map标记数a[i]最近的出现的下标。其实就是先求出这个区间的(异或和),然后异或上这个区间不同数的异或和(即由树状数组求出来的)。
#include <iostream>
#include <stdio.h>
#include <map>
#include <string.h>
#include <queue>
#include <algorithm>
#include <vector>
#define MAXN 1000005
#define INF 0x3f7f3f3f
using namespace std;
struct node
{
int l,r,id;
}p[MAXN];
bool cmp(node x,node y)
{
if(x.r==y.r)return x.l<y.l;
return x.r<y.r;
}
int c[MAXN],a[MAXN],ans[MAXN],cnt[MAXN];
int n;
void add(int x,int val)
{
while(x<=n)
{
c[x]^=val;
x+=(-x)&x;
}
}
int quary(int x)
{
int sum=0;
while(x>0)
{
sum^=c[x];
x-=(-x)&x;
}
return sum;
}
map<int,int>pre;
int main()
{
int q,i,j;
while(scanf("%d",&n)!=EOF)
{
pre.clear();
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d",&p[i].l,&p[i].r);
p[i].id=i;
}
sort(p+1,p+1+q,cmp);
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
memset(cnt,0,sizeof(cnt));
j=1;
for(i=1;i<=n;)
{
int flag=0;
while(i<=p[j].r)
{
cnt[i]=cnt[i-1]^a[i];
if(pre.find(a[i])==pre.end())
{
pre[a[i]]=i;
add(i,a[i]);
}
else
{
int id=pre[a[i]];
pre[a[i]]=i;
add(id,a[i]);
add(i,a[i]);
}
while(i==p[j].r)
{
int temp=quary(p[j].r)^quary(p[j].l-1);
ans[p[j].id]=(cnt[i]^cnt[p[j].l-1])^temp;
if(j>=q)
{
flag=1;break;
}
j++;
}
if(flag==1)break;
i++;
}
if(flag)break;
}
for(i=1;i<=q;i++)
{
printf("%d\n",ans[i]);
}
}
return 0;
}