抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

传送门

小清新莫队题,考虑两个相同的数异或起来会抵消,设sumi=a1a2....aisum_i=a_1⨁a_2⨁....⨁a_i我们有axax+1....ay=sumysumx1a_x ⨁ a_{x+1} ⨁ .... ⨁ a_y=sum_y ⨁ sum_{x-1}

这样就好办了,设当前维护的区间为[l,r][l,r],我们开一个桶cnt[x]cnt[x],记录sum[i]i[l,r]sum[i] i \in [l,r],出现了多少次。

考虑新加进一个下标为pp的数,把sumysumx1=ksum_y ⨁ sum_{x-1}=k转换成sumy=ksumx1sum_y=k ⨁ sum_{x-1},于是ans+=cnt[a[p]k]ans+=cnt[a[p] ⨁ k]即可。

减掉也是相同的,不在赘述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=(x<<3)+(x<<1)+(ch^'0');
ch=getchar();
}
return x*f;
}
int a[MAXN],cnt[MAXN],pos[MAXN],k,ans;
inline void Add(int x){
ans+=cnt[x^k],++cnt[x];
}
inline void Del(int x){
--cnt[x],ans-=cnt[x^k];
}
struct Query{
int l,r,id;
}q[MAXN];
inline bool operator < (const Query &a,const Query &b){
return (pos[a.l]^pos[b.l])?pos[a.l]<pos[b.l]:((pos[a.l]&1)?a.r<b.r:a.r>b.r);
}
int Ans[MAXN];
int main(){
int n=read(),m=read();k=read();
int Size=(int)(sqrt(n));
for (register int i=1;i<=n;++i){
a[i]=a[i-1]^read();
pos[i]=(i-1)/Size+1;
}
for (register int i=1;i<=m;++i){
q[i]=Query{read()-1,read(),i};
}
sort(q+1,q+1+m);
int l=1,r=0;
for (register int i=1;i<=m;++i){
while (l>q[i].l) Add(a[--l]);
while (r<q[i].r) Add(a[++r]);
while (l<q[i].l) Del(a[l++]);
while (r>q[i].r) Del(a[r--]);
Ans[q[i].id]=ans;
}
for (register int i=1;i<=m;++i){
printf("%d\n",Ans[i]);
}
}

评论