題目描述
已知一個長度為n的整數數列 $a_1,a_2,...,a_n$,給定查詢參數l、r,問在 $a_l,a_{l+1},...,a_r$ 區間內,有多少子序列滿足異或和等於k。也就是說,對於所有的x,y (I ≤ x ≤ y ≤ r),能夠滿足$a_x\bigoplus a_{x+1} \bigoplus ... \bigoplus a_y = k$的x,y有多少組。
思路
記一個異或前綴和 val,問題就轉換成有多少對數異或等於 k
直接上莫隊
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
int n,m,k,block,cnt[maxn],val[maxn];
long long tot,ans[maxn];
struct Query {
int l,r,num;
inline bool operator < (Query cmp) const {
if (l/block != cmp.l/block) return l/block < cmp.l/block;
return r/block < cmp.r/block;
}
}q[maxn];
inline void add(int x) { tot += cnt[x^k]; cnt[x]++; }
inline void del(int x) { tot -= cnt[x^k]+(!k); cnt[x]--; }
int main() {
scanf("%d%d%d",&n,&m,&k);
block = sqrt(n);
for (int i = 1;i <= n;i++) scanf("%d",&val[i]),val[i] ^= val[i-1];
for (int i = 1;i <= m;i++) {
scanf("%d%d",&q[i].l,&q[i].r);
q[i].l--;
q[i].num = i;
}
sort(q+1,q+m+1);
int l = 1,r = 0;
for (int i = 1;i <= m;i++) {
while (l > q[i].l) add(val[--l]);
while (l < q[i].l) del(val[l++]);
while (r < q[i].r) add(val[++r]);
while (r > q[i].r) del(val[r--]);
ans[q[i].num] = tot;
}
for (int i = 1;i <= m;i++) printf("%lld\n",ans[i]);
return 0;
}
