5301: [Cqoi2018]异或序列
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 400 Solved: 291
[Submit][Status][Discuss]
Description
已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子
序列满足异或和等于 k 。
也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。
Input
输入文件第一行,为3个整数n,m,k。
第二行为空格分开的n个整数,即ai,a2,….an。
接下来m行,每行两个整数lj,rj,表示一次查询。
1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n
Output
输出文件共m行,对应每个查询的计算结果。
Sample Input
4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4
1 2 3 1
1 4
1 3
2 3
2 4
4 4
Sample Output
4
2
1
2
1
2
1
2
1
没什么说的,注意右区间操作时,要考虑左边的前缀。
#include<bits/stdc++.h> using namespace std; const int maxn=100010; struct in{int l,r,g,id;}s[maxn]; bool cmp(in w,in v){if(w.g!=v.g) return w.g<v.g; return w.r<v.r;} int sum[maxn],cnt[maxn]; long long ans[maxn]; int main() { int N,M,K,L,R,B,res; scanf("%d%d%d",&N,&M,&K); B=sqrt(N); for(int i=1;i<=N;i++) scanf("%d",&sum[i]),sum[i]^=sum[i-1]; L=1; R=res=0; for(int i=1;i<=M;i++){ scanf("%d%d",&s[i].l,&s[i].r); s[i].id=i; s[i].g=s[i].l/B; } sort(s+1,s+M+1,cmp); for(int i=1;i<=M;i++) { while(R<s[i].r) cnt[sum[++R]]++,res+=cnt[sum[R]^K]+((sum[R]^K)==sum[L-1]); while(R>s[i].r) res-=cnt[sum[R]^K]+((sum[R]^K)==sum[L-1]),cnt[sum[R--]]--; while(L<s[i].l) res-=cnt[sum[L-1]^K],cnt[sum[L++]]--; while(L>s[i].l) cnt[sum[--L]]++,res+=cnt[sum[L-1]^K]; ans[s[i].id]=res; } for(int i=1;i<=M;i++) printf("%lld ",ans[i]); return 0; }