区间出现偶数次的数的异或和
题目描述
初始给定n个卡片拍成一排,其中第i个卡片上的数为x[i]。
有q个询问,每次询问给定L和R表示,询问的区间【L,R】内的卡片所有出现了偶数次的数的异或和是多少。
输入
输入一行两个整数n,q。
第二行n个整数,第i个数为x[i]。
接下来q行,每行两个整数L和R,表示询问的区间。
输出
输出q行,其中第i行表示第i次询问的区间出现偶数次的数的异或和。
样例输入
3 1
3 7 8
1 3
样例输出
0
solution
①、区间内出现偶数次的数异或和 = 区间内出现奇数次的数的异或和^区间内出现过的数的异或和
②、区间内出现奇数次的数的异或和 = 区间所有数的异或和
所以,区间内出现偶数次的数异或和 = 区间所有数的异或和^区间内出现过的数的异或和
于是问题转化成求区间内出现过的数的异或和:
这里树状数组sum(i)的含义就是指以当前i为结尾的前缀区间的不同数的异或和
先对询问按右端点排序
然后遍历每个询问,对于当前位置p,如果当前位置上的数x在之前出现过,把它在之前位置上的影响删除:
$ add(last[x],x);//由异或的性质可以知道,再异或一次就可以消除影响) $
把它在当前位置的影响插入:
$ add(p,x); $
更新记录最后位置的数组 $ last[i] $
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#define re register
#define ll long long
using namespace std ;
const int maxn = 1000005 ;
inline int read () {
int f = 1 , x = 0 ;
char ch = getchar () ;
while(ch > '9' || ch < '0') {if(ch == '-') f = -1 ; ch = getchar () ;}
while(ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;}
return x * f ;
}
int n , q , x[maxn] ;
int xorsum[maxn] , ans[maxn] , b[maxn] ;
int last[maxn] ;
struct Tree {
int l , r , ind ;
}tree[maxn] ;
bool cmp(Tree a , Tree b) {
return a.r < b.r ;
}
inline int lowbit(int x) {
return x & -x ;
}
inline void add(int pos , int val){
while(pos <= n) {
b[pos] ^= val ;
pos += lowbit(pos) ;
}
}
inline int sum(int pos) {
int res = 0 ;
while (pos >= 1) {
res ^= b[pos] ;
pos -= lowbit(pos) ;
}
return res ;
}
int main() {
freopen("C.in" , "r" , stdin) ;
freopen("C.out" , "w" , stdout) ;
n = read () ; q = read () ;
for(re int i = 1 ; i <= n ; ++ i) {
x[i] = read () ;
xorsum[i] = xorsum[i - 1] ^ x[i] ;
}
for(re int i = 1 ; i <= q ; ++ i) {
tree[i].l = read () ; tree[i].r = read () ;
tree[i].ind = i ;
}
sort(tree + 1 , tree + q + 1 , cmp) ;
for(re int i = 1 , j = 1 ; i <= q ; ++ i) {
while(j <= tree[i].r) {
if(last[x[j]])
add(last[x[j]] , x[j]) ;
last[x[j]] = j ;
add(j , x[j]) ;
j++ ;
}
ans[tree[i].ind] = sum(tree[i].r) ^ sum(tree[i].l - 1) ^ xorsum[tree[i].r] ^ xorsum[tree[i].l - 1] ;
}
for(re int i = 1 ; i <= q ; ++ i)
printf("%d\n" , ans[i]) ;
return 0 ;
}
顺风不浪,逆风不怂。