Codeforces 617E XOR and Favorite Number(莫队算法)

时间:2023-03-09 07:38:56
Codeforces 617E XOR and Favorite Number(莫队算法)

题目大概说给一个序列,多次询问区间异或和为k的连续子序列有多少个。

莫队算法,利用异或的性质,通过前缀和求区间和,先处理出序列各个前缀和,然后每次区间转移时维护i以及i-1前缀和为某数的个数并增加或减少对答案的贡献。

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN (1<<20) int block;
struct Query{
int l,r,i;
bool operator<(const Query &q) const {
if(l/block==q.l/block) return r<q.r;
return l/block<q.l/block;
}
}query[]; int n,m,k,a[],sum[]; int cnt1[MAXN],cnt2[MAXN];
long long ans;
void left_insert(int i){
++cnt1[sum[i-]];
++cnt2[sum[i]];
ans+=cnt2[sum[i-]^k];
}
void left_remove(int i){
ans-=cnt2[sum[i-]^k];
--cnt1[sum[i-]];
--cnt2[sum[i]];
}
void right_insert(int i){
++cnt1[sum[i-]];
++cnt2[sum[i]];
ans+=cnt1[sum[i]^k];
}
void right_remove(int i){
ans-=cnt1[sum[i]^k];
--cnt1[sum[i-]];
--cnt2[sum[i]];
} long long res[]; int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=; i<=n; ++i){
scanf("%d",a+i);
sum[i]=sum[i-]^a[i];
}
for(int i=; i<m; ++i){
scanf("%d%d",&query[i].l,&query[i].r);
query[i].i=i;
} block=(int)(sqrt(n)+1e-);
sort(query,query+m); int l=,r=;
right_insert();
for(int i=; i<m; ++i){
while(l<query[i].l) left_remove(l++);
while(l>query[i].l) left_insert(--l);
while(r<query[i].r) right_insert(++r);
while(r>query[i].r) right_remove(r--);
res[query[i].i]=ans;
} for(int i=; i<m; ++i){
printf("%lld\n",res[i]);
}
return ;
}