题意:查询区间中出现偶数次的数的异或和
树状数组
若是求奇数次的数的异或和,很好求区间[l,r]的异或和,即前r项异或和与前l-1项异或和异或即可
但这要求偶数次的,想办法把偶数的转化成奇数的,即区间中出现奇数次的异或和与不同数的异或和 异或 即可
出现的奇数次的异或和写前缀数组解决,不同数的用树状数组优化,用一个map映射my[x]表示x的上一步的位置
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <algorithm> using namespace std; const int N=1e6+9; int c[N],a[N],pre[N],n; struct P{ int l,r,ant,sub; }ans[N]; int cmp(P x,P y) { return x.r<y.r; } int cmp1(P x,P y) { return x.sub<y.sub; } int lowbit(int x) { return x&(-x); } void updata(int x,int y) //单点修改 { int i=x; while(i<=n) { c[i]^=y; i+=lowbit(i); } } int query(int x) //前x项求异或和 { int i=x,sum=0; while(i) { sum^=c[i]; i-=lowbit(i); } return sum; } int main() { scanf("%d",&n); map<int,int>my; my.clear(); memset(c,0,sizeof(c)); pre[0]=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pre[i]=pre[i-1]^a[i]; } int m; scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d%d",&ans[i].l,&ans[i].r); ans[i].sub=i; } int p=1; sort(ans,ans+m,cmp); for(int i=0;i<m;i++) { int l=ans[i].l,r=ans[i].r; while(p<=r) { if(my[a[p]]==0) { my[a[p]]=p; updata(p,a[p]); } else { updata(my[a[p]],a[p]); updata(p,a[p]); my[a[p]]=p; } p++; } ans[i].ant=pre[r]^pre[l-1]^query(r)^query(l-1); } sort(ans,ans+m,cmp1); for(int i=0;i<m;i++)00 printf("%d%c",ans[i].ant,i==m-1?‘\n‘:‘ ‘); return 0; }