题意:很多询问,求每个询问下,有多少个区间,异或=k。
分析:异或也有前缀和。[L,R] = pre[R] ^ pre[L-1];
莫队算法:是莫涛队长发明的,一种改良版的暴力离线算法。
首先将问题重新排序,有生成树的,有简单版的分块,然后通过一个区间去递推另个一区间的值。
这里需要记录一下flag[ pre[i] ] 的个数。
#include <bits/stdc++.h> using namespace std; const int maxn = 1<<20; int a[maxn]; struct Node { int l,r,id; }Q[maxn]; int pos[maxn]; long long ans[maxn]; long long flag[maxn]; bool cmp(Node a,Node b) { if(pos[a.l]==pos[b.l]) return a.r < b.r; return pos[a.l] < pos[b.l]; } int n,m,k; int L = 1,R = 0; long long Ans; void add(int x) { Ans+=flag[a[x]^k]; flag[a[x]]++; } void del(int x) { flag[a[x]]--; Ans-=flag[a[x]^k]; } int main() { scanf("%d%d%d",&n,&m,&k); int sz = sqrt(n); for(int i=1; i <= n; i++) { scanf("%d",&a[i]); a[i] = a[i]^a[i-1]; pos[i] = i/sz; } for(int i=1; i<=m ;i++) { scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id = i; } sort(Q+1,Q+m+1,cmp); flag[0] = 1; for(int i=1; i <=m; i++) { while(L<Q[i].l) { del(L-1); L++; } while(L>Q[i].l) { L--; add(L-1); } while(R<Q[i].r) { R++; add(R); } while(R>Q[i].r) { del(R); R--; } ans[Q[i].id] = Ans; } for(int i=1; i <= m; i++) printf("%I64d\n", ans[i]); return 0; }
时间: 2024-10-14 11:22:06