题目描述
已知一个长度为n的整数数列 a_1,a_2,...,a_na1,a2,...,an ,给定查询参数l、r,问在 a_l,a_{l+1},...,a_ral,al+1,...,ar 区间内,有多少子序列满足异或和等于k。也就是说,对于所有的x,y (I ≤ x ≤ y ≤ r),能够满足 a_x \bigoplus a_{x+1} \bigoplus ... \bigoplus a_y = k的x,y有多少组。
输入输出格式
输入格式:
输入文件第一行,为3个整数n,m,k。
第二行为空格分开的n个整数,即 a_1,a_2,..a_na1,a2,..an 。
接下来m行,每行两个整数 l_j,r_jlj,rj ,表示一次查询。
输出格式:
输出文件共m行,对应每个查询的计算结果。
思路
直接上莫队,统计的话,前缀和即可
#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; }