异或序列
异或序列
时间限制: 1 Sec 内存限制: 128 MB题目描述
已知一个长度为n的整数数列a1,a2,…,an,给定查询参数l、r,问在al,al+1,…,ar区间内,有多少子序列满足异或和等于k。也就是说,对于所有的x,y(l≤x≤y≤r),满足ax⊕ax+1⊕⋯⊕ay=k的x,y有多少组。
输入
输入第一行为3个整数n,m,k。第二行为空格分开的n个整数,即a1,a2,…,an。接下来m行,每行两个整数lj,rj,代表一次查询。
输出
输出共m行,对应每个查询的计算结果。
样例输入
4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4
样例输出
4
2
1
2
1
提示
对于30%的数据,1≤n,m≤1000。
对于100%的数据,1≤n,m≤105,0≤k,ai≤105,1≤lj≤rj≤n。
来源/分类
莫队:转移考虑维护sum数组,sum[i]表示当前区间内有多少个数和k异或为i。即x^k=i;
这样sum[i]就是有多少个数和i异或为k。
#include<bits/stdc++.h> #define N 100500 using namespace std; int a[N+5]; int sum[N*10+5]= {0}; int l,r,n,k,base; int l_l_move() { if(l<=0)return 0; l--; int now=sum[a[l]]; sum[a[l]^k]++; return now; } int r_r_move() { if(r>=n)return 0; r++; int now=sum[a[r]]; sum[a[r]^k]++; return now; } int l_r_move() { if(l>=n)return 0; sum[a[l]^k]--; int now=sum[a[l]]; l++; return now; } int r_l_move() { if(r<=0)return 0; sum[a[r]^k]--; int now=sum[a[r]]; r--; return now; } typedef struct { int l,r,index,ans; } ss; int cmp(ss a,ss b) { if(a.l/base!=b.l/base)return (a.l/base)<(b.l/base); return a.r<b.r; } ss Array[N]; long long Ans[N]; int main() { int m; scanf("%d %d %d",&n,&m,&k); base=sqrt(n); for(int i=1; i<=n; i++)scanf("%d",&a[i]); for(int i=2; i<=n; i++)a[i]=a[i-1]^a[i]; for(int i=1; i<=m; i++) scanf("%d %d",&Array[i].l,&Array[i].r),Array[i].index=i; sort(Array+1,Array+1+m,cmp); long long ans=0; l=r=Array[1].l; sum[a[l]^k]++; for(int i=1; i<=m; i++) { Array[i].l--; while(l<Array[i].l)ans-=l_r_move(); while(l>Array[i].l)ans+=l_l_move(); while(r>Array[i].r)ans-=r_l_move(); while(r<Array[i].r)ans+=r_r_move(); Ans[Array[i].index]=ans; } for(int i=1; i<=m; i++) printf("%lld\n",Ans[i]); return 0; }
路漫漫其修远兮,吾将上下而求索