题意:给你一个长为n的序列,在给你一个m次询问,每次询问区间内能有多少个连续子序列的异或和为k
题解:还是莫队啊,暴力搞事情啊。假设a^b=k, 那么我们每次莫队add的时候只要ans加一次mp[a[x]^k]的个数就好(del同理)。对了要处理出前缀异或和,mp维护的查询区间内的异或前缀和。因为两个前缀异或和进行异或就能得出中间这段的异或和
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #include<ctime> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=1<<20; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; ll a[N]; struct node { int l,r,id; }Q[N]; int pos[N]; bool cmp(node x,node y){ if(pos[x.l]==pos[y.l])return x.r<y.r; return pos[x.l]<pos[y.l]; } int L=1,R=0; ll ans=0; ll res[N]; int n,q,k; ll mp[N]; void del(int x){ mp[a[x]]--; ans-=mp[a[x]^k]; } void add(int x){ ans+=mp[a[x]^k]; mp[a[x]]++; } int main(){ scanf("%d%d%d",&n,&q,&k); int sz=sqrt(n); for(int i=1;i<=n;i++){ scanf("%I64d",&a[i]); a[i]=a[i]^a[i-1]; pos[i]=i/sz; } for(int i=1;i<=q;i++){ scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id=i; } sort(Q+1,Q+1+q,cmp); mp[0]=1; for(int i=1;i<=q;i++){ while(L<Q[i].l){ del(L-1); L++; } while(L>Q[i].l){ L--; add(L-1); } while(R>Q[i].r){ del(R); R--; } while(R<Q[i].r){ R++; add(R); } res[Q[i].id]=ans; } for(int i=1;i<=q;i++){ printf("%I64d ",res[i]); } return 0; }