题目大意:给一个长度为n的序列,m次询问,询问为区间中所有出现了偶数次的数的异或和。
题解:由于区间的异或和剩下的是出现奇数次的数,每次询问的答案即为 x^y x=区间内所有出现了的数的异或和 y=区间内出现了奇数次的数的异或和.如果在线询问的话x不好维护。所以离线处理,如果这个数出现过就抹去之前出现的点,保证每个数只出现一次。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
#define maxn 4001000
#define pb push_back
#define mp make_pair
#define ft first
#define sd second
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define getmid int mid=(l+r)>>1
map<int,int>myp;
vector<pair<int,int> >g[maxn];
int ans[maxn];
int siz,n,pre[maxn],xorsum[maxn],a[maxn],m;
void pushup(int rt)
{
xorsum[rt]=xorsum[rt<<1]^xorsum[rt<<1|1];
}
int query(int l,int r,int rt,int st,int ed)
{
if(st<=l&&r<=ed)
{
return xorsum[rt];
}
getmid;
int t1=0,t2=0;
if(st<=mid)
t1=query(lson,st,ed);
if(ed>mid)
t2=query(rson,st,ed);
return t1^t2;
}
void update(int l,int r,int rt,int pos,int f)
{
if(l==r)
{
xorsum[rt]^=f;
return;
}
getmid;
if(pos<=mid) update(lson,pos,f);
else update(rson,pos,f);
pushup(rt);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pre[i]=pre[i-1]^a[i];
}
int l,r;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
g[r].pb(mp(l,i));
}
int ll,rr;
for(int i=1;i<=n;i++)
{
if(myp[a[i]]!=0) update(1,n,1,myp[a[i]],a[i]);
update(1,n,1,i,a[i]);
myp[a[i]]=i;
rr=i;
for(int j=0;j<g[i].size();j++)
{
ll=g[i][j].ft;
ans[g[i][j].sd]=pre[rr]^pre[ll-1]^query(1,n,1,ll,rr);
}
}
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}